Merge branch 'release'

This commit is contained in:
Veronica Berglyd Olsen
2024-07-04 16:30:26 +02:00
22 changed files with 7326 additions and 2185 deletions
+116
View File
@@ -0,0 +1,116 @@
{
"Synopsis": "Streszczenie",
"Short Description": "Krótki opis",
"Comment": "Komentarz",
"Notes": "Notatki",
"Tag": "Znacznik",
"Point of View": "Punkt widzenia",
"Focus": "Skupienie",
"Characters": "Postacie",
"Plot": "Fabuła",
"Timeline": "Oś czasu",
"Locations": "Miejsca",
"Objects": "Obiekty",
"Entities": "Podmioty",
"Custom": "Różne",
"0": "zero",
"1": "pierwszy",
"2": "drugi",
"3": "trzeci",
"4": "czwarty",
"5": "piąty",
"6": "szósty",
"7": "siódmy",
"8": "ósmy",
"9": "dziewiąty",
"10": "dziesiąty",
"11": "jedenasty",
"12": "dwunasty",
"13": "trzynasty",
"14": "czternasty",
"15": "piętnasty",
"16": "szesnasty",
"17": "siedemnasty",
"18": "osiemnasty",
"19": "dziewiętnasty",
"20": "dwudziesty",
"21": "dwudziesty pierwszy",
"22": "dwudziesty drugi",
"23": "dwudziesty Trzeci",
"24": "dwudziesty czwarty",
"25": "dwudziesty piąty",
"26": "dwudziesty szósty",
"27": "dwudziesty siódmy",
"28": "dwudziesty ósmy",
"29": "dwudziesty dziewiąty",
"30": "trzydziesty",
"31": "trzydziesty pierwszy",
"32": "trzydziesty drugi",
"33": "trzydziesty trzeci",
"34": "trzydziesty czwarty",
"35": "trzydziesty piąty",
"36": "trzydziesty szósty",
"37": "trzydziesty siódmy",
"38": "trzydziesty ósmy",
"39": "trzydziesty dziewiaty",
"40": "czterdziesty",
"41": "czterdziesty pierwszy",
"42": "czterdziesty drugi",
"43": "czterdziesty Trzeci",
"44": "czterdziesty czwarty",
"45": "czterdziesty piąty",
"46": "czterdziesty szósty",
"47": "czterdziesty siódmy",
"48": "czterdziesty ósmy",
"49": "czterdziesty dziewiąty",
"50": "pięćdziesiąty",
"51": "pięćdziesiąty pierwszy",
"52": "pięćdziesiąty drugi",
"53": "pięćdziesiąty trzeci",
"54": "pięćdziesiąty czwarty",
"55": "pięćdziesiąty piąty",
"56": "pięćdziesiąty szósty",
"57": "pięćdziesiąty siódmy",
"58": "pięćdziesiąty ósmy",
"59": "pięćdziesiąty dziewiąty",
"60": "sześćdziesiąty",
"61": "sześćdziesiąty pierwszy",
"62": "sześćdziesiąty drugi",
"63": "sześćdziesiąty trzeci",
"64": "sześćdziesiąty czwarty",
"65": "sześćdziesiąty piąty",
"66": "sześćdziesiąty szósty",
"67": "sześćdziesiąty siódmy",
"68": "sześćdziesiąty ósmy",
"69": "sześćdziesiąty dziewiąty",
"70": "siedemdziesiąty",
"71": "siedemdziesiąty pierwszy",
"72": "siedemdziesiąty drugi",
"73": "siedemdziesiąty trzeci",
"74": "siedemdziesiąty czwarty",
"75": "siedemdziesiąty piąty",
"76": "siedemdziesiąty szósty",
"77": "siedemdziesiąty siódmy",
"78": "siedemdziesiąty ósmy",
"79": "siedemdziesiąty dziewiąty",
"80": "osiemdziesiąty",
"81": "osiemdziesiąty pierwszy",
"82": "osiemdziesiąty drugi",
"83": "osiemdziesiąty trzeci",
"84": "osiemdziesiąty czwarty",
"85": "osiemdziesiąty piąty",
"86": "osiemdziesiąty szósty",
"87": "osiemdziesiąty siódmy",
"88": "osiemdziesiąty ósmy",
"89": "osiemdziesiąty dziewiąty",
"90": "dziewięćdziesiąty",
"91": "dziewięćdziesiąty pierwszy",
"92": "dziewięćdziesiąty drugi",
"93": "dziewięćdziesiąty trzeci",
"94": "dziewięćdziesiąty czwarty",
"95": "dziewięćdziesiąty piąty",
"96": "dziewięćdziesiąty szósty",
"97": "dziewięćdziesiąty siódmy",
"98": "dziewięćdziesiąty ósmy",
"99": "dziewięćdziesiąty dziewiąty"
}
+52 -44
View File
@@ -1,84 +1,92 @@
<!DOCTYPE html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<h3>Main Developer</h3>
<p>Veronica Berglyd Olsen (<a href="https://github.com/vkbo">@vkbo</a>)</p>
<p>Veronica Berglyd Olsen</p>
<h3>Contributors</h3>
<p>
&nbsp;&bull;&nbsp;<b>Concept:</b> Marian Lückhof (<a href="https://github.com/Number042">@Number042</a>)<br>
&nbsp;&bull;&nbsp;<b>Internationalisation:</b> Bruno Meneguello (<a href="https://github.com/bkmeneguello">@bkmeneguello</a>)<br>
&nbsp;&bull;&nbsp;<b>Setup and Packaging:</b> Rachel Powers (<a href="https://github.com/Ryex">@Ryex</a>)
</p>
<ul>
<li><b>Early Concept:</b> Marian Lückhof</li>
<li><b>Internationalisation:</b> Bruno Meneguello</li>
<li><b>Setup and Packaging:</b> Rachel Powers</li>
</ul>
<p>For other contributions, see the project's
<a href="https://github.com/vkbo/novelWriter/graphs/contributors">Contributors</a> page.</p>
<h3>Artwork</h3>
<p>The artwork on the Welcome dialog was created by <a href="https://louisdurrant.art">Louis Durrant</a>.</p>
<p>The artwork on the Welcome dialog was created by Louis Durrant.</p>
<h3>Translations</h3>
<p>The default language is English (UK) with English (US) as an option. These are the original
translators for the languages currently available:</p>
<p>
&nbsp;&bull;&nbsp;<b>Dutch:</b> Martijn van der Kleijn (<a href="https://github.com/mvdkleijn">@mvdkleijn</a>)<br>
&nbsp;&bull;&nbsp;<b>French:</b> Jan Lüdke (<a href="https://github.com/jyhelle">@jyhelle</a>)<br>
&nbsp;&bull;&nbsp;<b>German:</b> Myian (<a href="https://github.com/heymyian">@heymyian</a>)<br>
&nbsp;&bull;&nbsp;<b>Italian:</b> Riccardo Mangili<br>
&nbsp;&bull;&nbsp;<b>Japanese:</b> hebekeg (<a href="https://github.com/hebekeg">@hebekeg</a>)<br>
&nbsp;&bull;&nbsp;<b>Latin American Spanish:</b> Tommy Marplatt (<a href="https://github.com/tmarplatt">@tmarplatt</a>)<br>
&nbsp;&bull;&nbsp;<b>Norwegian:</b> Veronica Berglyd Olsen (<a href="https://github.com/vkbo">@vkbo</a>)<br>
&nbsp;&bull;&nbsp;<b>Portuguese:</b> Bruno Meneguello (<a href="https://github.com/bkmeneguello">@bkmeneguello</a>)<br>
&nbsp;&bull;&nbsp;<b>Simplified Chinese:</b> Qianzhi Long (<a href="https://github.com/longqzh">@longqzh</a>)
</p>
<ul>
<li><b>Dutch:</b> Martijn van der Kleijn (mvdkleijn)</li>
<li><b>French:</b> Jan Lüdke (jyhelle)</li>
<li><b>German:</b> Myian (HeyMyian)</li>
<li><b>Italian:</b> Riccardo Mangili</li>
<li><b>Japanese:</b> hebekeg</li>
<li><b>Latin American Spanish:</b> Tommy Marplatt (tmarplatt)</li>
<li><b>Norwegian:</b> Veronica Berglyd Olsen (vkbo)</li>
<li><b>Polish:</b> Anna Maria Polak (Nauthiz)</li>
<li><b>Portuguese:</b> Bruno Meneguello (bkmeneguello)</li>
<li><b>Simplified Chinese:</b> Qianzhi Long (longqzh)</li>
</ul>
<p>Additional larger translation contributions:</p>
<p>
&nbsp;&bull;&nbsp;<b>French:</b> Albert Aribaud (<a href="https://github.com/aaribaud">@aaribaud</a>)
</p>
<ul>
<li><b>French:</b> Albert Aribaud (aaribaud)</li>
<li><b>Portuguese:</b> Oli Maia (olimaia)</li>
</ul>
<p>Translations are managed on <a href="https://crowdin.com/project/novelwriter">Crowdin</a>, and
more contributions are listed on the project's <a href="https://crowdin.com/project/novelwriter/members">Members</a> page.</p>
more contributions are listed on the project's Members page.</p>
<h3>Libraries</h3>
<p>The following libraries are dependencies of novelWriter:</p>
<p>
&nbsp;&bull;&nbsp;<a href="https://www.qt.io">Qt5</a> by Qt Company<br>
&nbsp;&bull;&nbsp;<a href="https://www.riverbankcomputing.com/software/pyqt">PyQt5</a> by Riverbank Computing<br>
&nbsp;&bull;&nbsp;<a href="https://abiword.github.io/enchant">Enchant</a> by Dom Lachowicz<br>
&nbsp;&bull;&nbsp;<a href="https://pyenchant.github.io/pyenchant">PyEnchant</a> by Dimitri Merejkowsky
</p>
<ul>
<li><b>Qt5</b> by Qt Company</li>
<li><b>PyQt5</b> by Riverbank Computing</li>
<li><b>Enchant</b> by Dom Lachowicz</li>
<li><b>PyEnchant</b> by Dimitri Merejkowsky</li>
</ul>
<h3>Assets</h3>
<p>Some of the assets bundled with novelWriter were adapted from the following sources:</p>
<p>
&nbsp;&bull;&nbsp;<a href="https://github.com/stephenhutchings/typicons.font">Typicons</a> icons by Stephen Hutchings (CC BY-SA 4.0)<br>
&nbsp;&bull;&nbsp;<a href="https://github.com/chriskempson/base16">Tomorrow</a> syntax themes by Chris Kempson (MIT License)<br>
&nbsp;&bull;&nbsp;<a href="https://github.com/sdras/night-owl-vscode-theme">Owl</a> syntax themes by Sarah Drasner (MIT License)<br>
&nbsp;&bull;&nbsp;<a href="https://github.com/altercation/solarized">Solarized</a> themes by Ethan Schoonover (MIT License)<br>
&nbsp;&bull;&nbsp;<a href="https://github.com/alemvigh">Cyberpunk Night</a> theme by Anders Lemvigh (CC BY-SA 4.0)<br>
&nbsp;&bull;&nbsp;<a href="https://draculatheme.com">Dracula</a> theme by Zeno Rocha (MIT License)<br>
&nbsp;&bull;&nbsp;<a href="https://github.com/loilo/vscode-snazzy-light">Snazzy Light</a> theme by Florian Reuschel (MIT License)
</p>
<ul>
<li><b>Typicons</b> icons by Stephen Hutchings (CC BY-SA 4.0)</li>
<li><b>Tomorrow</b> syntax themes by Chris Kempson (MIT License)</li>
<li><b>Owl</b> syntax themes by Sarah Drasner (MIT License)</li>
<li><b>Solarized</b> themes by Ethan Schoonover (MIT License)</li>
<li><b>Cyberpunk Night</b> theme by Anders Lemvigh (CC BY-SA 4.0)</li>
<li><b>Dracula</b> theme by Zeno Rocha (MIT License)</li>
<li><b>Snazzy Light</b> theme by Florian Reuschel (MIT License)</li>
</ul>
<h3>Fonts</h3>
<p>The font used for the main novelWriter logo, mimetype and text banners is Pridi. Other fonts are
used on buttons and icons.</p>
<p>
&nbsp;&bull;&nbsp;Pridi by Cadson Demak (Open Font License, Version 1.1)<br>
&nbsp;&bull;&nbsp;Source Sans Pro by Paul D. Hunt (SIL Open Font License)
</p>
<ul>
<li><b>Pridi</b> by Cadson Demak (Open Font License, Version 1.1)</li>
<li><b>Source Sans Pro</b> by Paul D. Hunt (SIL Open Font License)</li>
</ul>
<h3>Special Mentions</h3>
<p>Additional thanks to <a href="https://github.com/johnblommers">@johnblommers</a> who was an early user and who has provided a lot
of very useful feedback over the years.</p>
<p>Additional thanks to John Blommers who was an early user and who has provided a lot of very
useful feedback over the years.</p>
</body>
</html>
+14 -4
View File
@@ -254,13 +254,23 @@ class NWProject:
status = self._storage.initProjectStorage(projPath, clearLock)
if status != NWStorageOpen.READY:
if status == NWStorageOpen.UNKOWN:
SHARED.error(self.tr("Not a known project file format."))
SHARED.error(
self.tr("Not a known project file format."),
info=self.tr("Path: {0}").format(str(projPath))
)
elif status == NWStorageOpen.NOT_FOUND:
SHARED.error(self.tr("Project file not found."))
SHARED.error(
self.tr("Project file not found."),
info=self.tr("Path: {0}").format(str(projPath))
)
elif status == NWStorageOpen.FAILED:
SHARED.error(
self.tr("Failed to open project."),
info=self.tr("Path: {0}").format(str(projPath)),
exc=self._storage.exc
)
elif status == NWStorageOpen.LOCKED:
self._state = NWProjectState.LOCKED
elif status == NWStorageOpen.FAILED:
SHARED.error(self.tr("Failed to open project."), exc=self._storage.exc)
return False
# Read Project XML
+9 -22
View File
@@ -29,8 +29,8 @@ import logging
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence
from PyQt5.QtWidgets import (
QAbstractButton, QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout,
QLineEdit, QPushButton, QVBoxLayout, QWidget
QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit,
QPushButton, QVBoxLayout, QWidget
)
from novelwriter import CONFIG, SHARED
@@ -43,10 +43,7 @@ from novelwriter.extensions.modified import (
)
from novelwriter.extensions.pagedsidebar import NPagedSideBar
from novelwriter.extensions.switch import NSwitch
from novelwriter.types import (
QtAlignCenter, QtDialogApply, QtDialogClose, QtDialogSave, QtRoleAccept,
QtRoleApply, QtRoleReject
)
from novelwriter.types import QtAlignCenter, QtDialogCancel, QtDialogSave
logger = logging.getLogger(__name__)
@@ -89,8 +86,9 @@ class GuiPreferences(NDialog):
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
# Buttons
self.buttonBox = QDialogButtonBox(QtDialogApply | QtDialogSave | QtDialogClose, self)
self.buttonBox.clicked.connect(self._dialogButtonClicked)
self.buttonBox = QDialogButtonBox(QtDialogSave | QtDialogCancel, self)
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self.reject)
# Assemble
self.searchBox = QHBoxLayout()
@@ -784,19 +782,6 @@ class GuiPreferences(NDialog):
# Private Slots
##
@pyqtSlot("QAbstractButton*")
def _dialogButtonClicked(self, button: QAbstractButton) -> None:
"""Handle button clicks from the dialog button box."""
role = self.buttonBox.buttonRole(button)
if role == QtRoleApply:
self._saveValues()
elif role == QtRoleAccept:
self._saveValues()
self.close()
elif role == QtRoleReject:
self.close()
return
@pyqtSlot(int)
def _sidebarClicked(self, section: int) -> None:
"""Process a user request to switch page."""
@@ -897,7 +882,7 @@ class GuiPreferences(NDialog):
CONFIG.setPreferencesWinSize(self.width(), self.height())
return
def _saveValues(self) -> None:
def _doSave(self) -> None:
"""Save the values set in the form."""
updateTheme = False
needsRestart = False
@@ -1012,4 +997,6 @@ class GuiPreferences(NDialog):
CONFIG.saveConfig()
self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax)
self.close()
return
+18 -3
View File
@@ -281,13 +281,28 @@ class NColourLabel(QLabel):
return
def setTextColors(self, *, color: QColor | None = None, faded: QColor | None = None) -> None:
"""Set or update the text colours."""
self._color = color or self._color
self._faded = faded or self._faded
self._refeshTextColor()
return
def setColorState(self, state: bool) -> None:
"""Change the colour state."""
if self._state is not state:
self._state = state
colour = self.palette()
colour.setColor(QPalette.ColorRole.WindowText, self._color if state else self._faded)
self.setPalette(colour)
self._refeshTextColor()
return
def _refeshTextColor(self) -> None:
"""Refresh the colour of the text on the label."""
palette = self.palette()
palette.setColor(
QPalette.ColorRole.WindowText,
self._color if self._state else self._faded,
)
self.setPalette(palette)
return
+3 -3
View File
@@ -2919,10 +2919,10 @@ class GuiDocEditHeader(QWidget):
palette.setColor(QPalette.ColorRole.Window, SHARED.theme.colBack)
palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
self.setPalette(palette)
self.itemTitle.setPalette(palette)
self.itemTitle.setTextColors(
color=palette.windowText().color(), faded=SHARED.theme.fadedText
)
return
def changeFocusState(self, state: bool) -> None:
+3 -1
View File
@@ -741,7 +741,9 @@ class GuiDocViewHeader(QWidget):
palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
self.setPalette(palette)
self.itemTitle.setPalette(palette)
self.itemTitle.setTextColors(
color=palette.windowText().color(), faded=SHARED.theme.fadedText
)
return
def changeFocusState(self, state: bool) -> None:
+1
View File
@@ -268,6 +268,7 @@ class GuiOutlineToolBar(QToolBar):
self.aExport.setIcon(SHARED.theme.getIcon("export"))
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
self.novelLabel.setTextColors(color=self.palette().windowText().color())
return
def populateNovelList(self) -> None:
+30 -14
View File
@@ -1006,32 +1006,48 @@ class GuiMain(QMainWindow):
def _switchFocus(self, paneNo: nwFocus) -> None:
"""Switch focus between main GUI views."""
if paneNo == nwFocus.TREE:
if self.projStack.currentWidget() is self.projView:
if self.projView.treeHasFocus():
self._changeView(nwView.NOVEL)
self.novelView.setTreeFocus()
else:
self.projView.setTreeFocus()
elif self.projStack.currentWidget() is self.novelView:
if self.novelView.treeHasFocus():
self._changeView(nwView.PROJECT)
self.projView.setTreeFocus()
else:
self.novelView.setTreeFocus()
# Decision Matrix
# vM | vP | fP | vN | fN | Focus
# ----|----|----|----|----|---------
# T | T | T | F | F | Novel
# T | T | F | F | F | Project
# T | F | F | T | T | Project
# T | F | F | T | F | Novel
# T | F | F | F | F | Project
# F | T | T | F | F | Project
# F | T | F | F | F | Project
# F | F | F | T | T | Novel
# F | F | F | T | F | Novel
# F | F | F | F | F | Project
vM = self.mainStack.currentWidget() is self.splitMain
vP = self.projStack.currentWidget() is self.projView
vN = self.projStack.currentWidget() is self.novelView
fP = self.projView.treeHasFocus()
fN = self.novelView.treeHasFocus()
self._changeView(nwView.EDITOR)
if (vM and (vP and fP or vN and not fN)) or (not vM and vN):
self._changeView(nwView.NOVEL)
self.novelView.setTreeFocus()
else:
self._changeView(nwView.PROJECT)
self.projView.setTreeFocus()
elif paneNo == nwFocus.DOCUMENT:
self._changeView(nwView.EDITOR)
if self.docEditor.anyFocus():
hasViewer = self.splitView.isVisible()
if hasViewer and self.docEditor.anyFocus():
self.docViewer.setFocus()
elif self.docViewer.anyFocus():
elif hasViewer and self.docViewer.anyFocus():
self.docEditor.setFocus()
else:
self.docEditor.setFocus()
elif paneNo == nwFocus.OUTLINE:
self._changeView(nwView.OUTLINE)
self.outlineView.setTreeFocus()
return
@pyqtSlot(bool, bool, bool, bool)