From df19ced50cea50173e9bc87c6c03e9b150574bb4 Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Mon, 15 Feb 2021 16:47:57 +0100
Subject: [PATCH] Rewrap self.tr and fix a few bugs
---
nw/constants/__init__.py | 5 +-
nw/constants/constants.py | 126 +++++++++++----------
nw/core/document.py | 18 ++-
nw/core/index.py | 7 +-
nw/core/project.py | 226 ++++++++++++++++++++++----------------
nw/core/tohtml.py | 10 +-
nw/core/tokenizer.py | 13 ++-
nw/core/tree.py | 7 +-
nw/gui/about.py | 121 +++++++++++---------
nw/gui/build.py | 96 +++++++++-------
nw/gui/doceditor.py | 89 ++++++++-------
nw/gui/docmerge.py | 24 ++--
nw/gui/docsplit.py | 52 +++++----
nw/gui/docviewer.py | 16 ++-
nw/gui/itemdetails.py | 16 ++-
nw/gui/itemeditor.py | 27 +++--
nw/gui/mainmenu.py | 36 +++---
nw/gui/outline.py | 13 +--
nw/gui/outlinedetails.py | 40 +++----
nw/gui/projdetails.py | 22 ++--
nw/gui/projload.py | 9 +-
nw/gui/projsettings.py | 8 +-
nw/gui/projtree.py | 33 +++---
nw/gui/projwizard.py | 69 +++++++-----
nw/gui/theme.py | 13 ++-
nw/gui/writingstats.py | 21 +++-
nw/guimain.py | 73 +++++++-----
sample/nwProject.nwx | 8 +-
28 files changed, 682 insertions(+), 516 deletions(-)
diff --git a/nw/constants/__init__.py b/nw/constants/__init__.py
index 7c458d2e..0aeb0ae4 100644
--- a/nw/constants/__init__.py
+++ b/nw/constants/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from nw.constants.constants import (
- nwConst, nwLists, nwRegEx, nwFiles, nwKeyWords, nwLabels, nwQuotes,
- nwUnicode, nwHtmlUnicode
+ trConst, nwConst, nwLists, nwRegEx, nwFiles, nwKeyWords, nwLabels,
+ nwQuotes, nwUnicode, nwHtmlUnicode
)
from nw.constants.enum import (
nwAlert, nwDocAction, nwItemClass, nwItemLayout, nwItemType, nwOutline,
@@ -9,6 +9,7 @@ from nw.constants.enum import (
)
__all__ = [
+ "trConst",
"nwConst",
"nwLists",
"nwRegEx",
diff --git a/nw/constants/constants.py b/nw/constants/constants.py
index 892fcf6f..2135dce4 100644
--- a/nw/constants/constants.py
+++ b/nw/constants/constants.py
@@ -24,12 +24,18 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from PyQt5.QtCore import QT_TRANSLATE_NOOP
+from PyQt5.QtCore import QCoreApplication
+from PyQt5.QtCore import QT_TRANSLATE_NOOP as QT_TRN
from nw.constants.enum import (
nwItemClass, nwItemLayout, nwItemType, nwOutline
)
+def trConst(tString):
+ """Wrapper function for locally translating constants.
+ """
+ return QCoreApplication.translate("Constant", tString)
+
class nwConst():
# Date and Time Formats
@@ -121,17 +127,17 @@ class nwKeyWords:
class nwLabels():
CLASS_NAME = {
- nwItemClass.NO_CLASS : QT_TRANSLATE_NOOP("Constant", "None"),
- nwItemClass.NOVEL : QT_TRANSLATE_NOOP("Constant", "Novel"),
- nwItemClass.PLOT : QT_TRANSLATE_NOOP("Constant", "Plot"),
- nwItemClass.CHARACTER : QT_TRANSLATE_NOOP("Constant", "Characters"),
- nwItemClass.WORLD : QT_TRANSLATE_NOOP("Constant", "Locations"),
- nwItemClass.TIMELINE : QT_TRANSLATE_NOOP("Constant", "Timeline"),
- nwItemClass.OBJECT : QT_TRANSLATE_NOOP("Constant", "Objects"),
- nwItemClass.ENTITY : QT_TRANSLATE_NOOP("Constant", "Entity"),
- nwItemClass.CUSTOM : QT_TRANSLATE_NOOP("Constant", "Custom"),
- nwItemClass.ARCHIVE : QT_TRANSLATE_NOOP("Constant", "Outtakes"),
- nwItemClass.TRASH : QT_TRANSLATE_NOOP("Constant", "Trash"),
+ nwItemClass.NO_CLASS : QT_TRN("Constant", "None"),
+ nwItemClass.NOVEL : QT_TRN("Constant", "Novel"),
+ nwItemClass.PLOT : QT_TRN("Constant", "Plot"),
+ nwItemClass.CHARACTER : QT_TRN("Constant", "Characters"),
+ nwItemClass.WORLD : QT_TRN("Constant", "Locations"),
+ nwItemClass.TIMELINE : QT_TRN("Constant", "Timeline"),
+ nwItemClass.OBJECT : QT_TRN("Constant", "Objects"),
+ nwItemClass.ENTITY : QT_TRN("Constant", "Entity"),
+ nwItemClass.CUSTOM : QT_TRN("Constant", "Custom"),
+ nwItemClass.ARCHIVE : QT_TRN("Constant", "Outtakes"),
+ nwItemClass.TRASH : QT_TRN("Constant", "Trash"),
}
CLASS_FLAG = {
nwItemClass.NO_CLASS : "0",
@@ -160,15 +166,15 @@ class nwLabels():
nwItemClass.TRASH : "cls_trash",
}
LAYOUT_NAME = {
- nwItemLayout.NO_LAYOUT : QT_TRANSLATE_NOOP("Constant", "None"),
- nwItemLayout.TITLE : QT_TRANSLATE_NOOP("Constant", "Title Page"),
- nwItemLayout.BOOK : QT_TRANSLATE_NOOP("Constant", "Book"),
- nwItemLayout.PAGE : QT_TRANSLATE_NOOP("Constant", "Plain Page"),
- nwItemLayout.PARTITION : QT_TRANSLATE_NOOP("Constant", "Partition"),
- nwItemLayout.UNNUMBERED : QT_TRANSLATE_NOOP("Constant", "Unnumbered"),
- nwItemLayout.CHAPTER : QT_TRANSLATE_NOOP("Constant", "Chapter"),
- nwItemLayout.SCENE : QT_TRANSLATE_NOOP("Constant", "Scene"),
- nwItemLayout.NOTE : QT_TRANSLATE_NOOP("Constant", "Note"),
+ nwItemLayout.NO_LAYOUT : QT_TRN("Constant", "None"),
+ nwItemLayout.TITLE : QT_TRN("Constant", "Title Page"),
+ nwItemLayout.BOOK : QT_TRN("Constant", "Book"),
+ nwItemLayout.PAGE : QT_TRN("Constant", "Plain Page"),
+ nwItemLayout.PARTITION : QT_TRN("Constant", "Partition"),
+ nwItemLayout.UNNUMBERED : QT_TRN("Constant", "Unnumbered"),
+ nwItemLayout.CHAPTER : QT_TRN("Constant", "Chapter"),
+ nwItemLayout.SCENE : QT_TRN("Constant", "Scene"),
+ nwItemLayout.NOTE : QT_TRN("Constant", "Note"),
}
LAYOUT_FLAG = {
nwItemLayout.NO_LAYOUT : "Xo",
@@ -182,27 +188,27 @@ class nwLabels():
nwItemLayout.NOTE : "Nt",
}
KEY_NAME = {
- nwKeyWords.TAG_KEY : QT_TRANSLATE_NOOP("Constant", "Tag"),
- nwKeyWords.POV_KEY : QT_TRANSLATE_NOOP("Constant", "Point of View"),
- nwKeyWords.FOCUS_KEY : QT_TRANSLATE_NOOP("Constant", "Focus"),
- nwKeyWords.CHAR_KEY : QT_TRANSLATE_NOOP("Constant", "Characters"),
- nwKeyWords.PLOT_KEY : QT_TRANSLATE_NOOP("Constant", "Plot"),
- nwKeyWords.TIME_KEY : QT_TRANSLATE_NOOP("Constant", "Timeline"),
- nwKeyWords.WORLD_KEY : QT_TRANSLATE_NOOP("Constant", "Locations"),
- nwKeyWords.OBJECT_KEY : QT_TRANSLATE_NOOP("Constant", "Objects"),
- nwKeyWords.ENTITY_KEY : QT_TRANSLATE_NOOP("Constant", "Entities"),
- nwKeyWords.CUSTOM_KEY : QT_TRANSLATE_NOOP("Constant", "Custom"),
+ nwKeyWords.TAG_KEY : QT_TRN("Constant", "Tag"),
+ nwKeyWords.POV_KEY : QT_TRN("Constant", "Point of View"),
+ nwKeyWords.FOCUS_KEY : QT_TRN("Constant", "Focus"),
+ nwKeyWords.CHAR_KEY : QT_TRN("Constant", "Characters"),
+ nwKeyWords.PLOT_KEY : QT_TRN("Constant", "Plot"),
+ nwKeyWords.TIME_KEY : QT_TRN("Constant", "Timeline"),
+ nwKeyWords.WORLD_KEY : QT_TRN("Constant", "Locations"),
+ nwKeyWords.OBJECT_KEY : QT_TRN("Constant", "Objects"),
+ nwKeyWords.ENTITY_KEY : QT_TRN("Constant", "Entities"),
+ nwKeyWords.CUSTOM_KEY : QT_TRN("Constant", "Custom"),
}
OUTLINE_COLS = {
- nwOutline.TITLE : QT_TRANSLATE_NOOP("Constant", "Title"),
- nwOutline.LEVEL : QT_TRANSLATE_NOOP("Constant", "Level"),
- nwOutline.LABEL : QT_TRANSLATE_NOOP("Constant", "Document"),
- nwOutline.LINE : QT_TRANSLATE_NOOP("Constant", "Line"),
- nwOutline.CCOUNT : QT_TRANSLATE_NOOP("Constant", "Chars"),
- nwOutline.WCOUNT : QT_TRANSLATE_NOOP("Constant", "Words"),
- nwOutline.PCOUNT : QT_TRANSLATE_NOOP("Constant", "Pars"),
- nwOutline.POV : QT_TRANSLATE_NOOP("Constant", "POV"),
- nwOutline.FOCUS : QT_TRANSLATE_NOOP("Constant", "Focus"),
+ nwOutline.TITLE : QT_TRN("Constant", "Title"),
+ nwOutline.LEVEL : QT_TRN("Constant", "Level"),
+ nwOutline.LABEL : QT_TRN("Constant", "Document"),
+ nwOutline.LINE : QT_TRN("Constant", "Line"),
+ nwOutline.CCOUNT : QT_TRN("Constant", "Chars"),
+ nwOutline.WCOUNT : QT_TRN("Constant", "Words"),
+ nwOutline.PCOUNT : QT_TRN("Constant", "Pars"),
+ nwOutline.POV : QT_TRN("Constant", "POV"),
+ nwOutline.FOCUS : QT_TRN("Constant", "Focus"),
nwOutline.CHAR : KEY_NAME[nwKeyWords.CHAR_KEY],
nwOutline.PLOT : KEY_NAME[nwKeyWords.PLOT_KEY],
nwOutline.TIME : KEY_NAME[nwKeyWords.TIME_KEY],
@@ -210,7 +216,7 @@ class nwLabels():
nwOutline.OBJECT : KEY_NAME[nwKeyWords.OBJECT_KEY],
nwOutline.ENTITY : KEY_NAME[nwKeyWords.ENTITY_KEY],
nwOutline.CUSTOM : KEY_NAME[nwKeyWords.CUSTOM_KEY],
- nwOutline.SYNOP : QT_TRANSLATE_NOOP("Constant", "Synopsis"),
+ nwOutline.SYNOP : QT_TRN("Constant", "Synopsis"),
}
# END Class nwLabels
@@ -220,28 +226,28 @@ class nwQuotes():
Source: https://en.wikipedia.org/wiki/Quotation_mark
"""
SYMBOLS = {
- "\u0027" : QT_TRANSLATE_NOOP("Constant", "Straight single quotation mark"),
- "\u0022" : QT_TRANSLATE_NOOP("Constant", "Straight double quotation mark"),
+ "\u0027" : QT_TRN("Constant", "Straight single quotation mark"),
+ "\u0022" : QT_TRN("Constant", "Straight double quotation mark"),
- "\u2018" : QT_TRANSLATE_NOOP("Constant", "Left single quotation mark"),
- "\u2019" : QT_TRANSLATE_NOOP("Constant", "Right single quotation mark"),
- "\u201a" : QT_TRANSLATE_NOOP("Constant", "Single low-9 quotation mark"),
- "\u201b" : QT_TRANSLATE_NOOP("Constant", "Single high-reversed-9 quotation mark"),
- "\u201c" : QT_TRANSLATE_NOOP("Constant", "Left double quotation mark"),
- "\u201d" : QT_TRANSLATE_NOOP("Constant", "Right double quotation mark"),
- "\u201e" : QT_TRANSLATE_NOOP("Constant", "Double low-9 quotation mark"),
- "\u201f" : QT_TRANSLATE_NOOP("Constant", "Double high-reversed-9 quotation mark"),
- "\u2e42" : QT_TRANSLATE_NOOP("Constant", "Double low-reversed-9 quotation mark"),
+ "\u2018" : QT_TRN("Constant", "Left single quotation mark"),
+ "\u2019" : QT_TRN("Constant", "Right single quotation mark"),
+ "\u201a" : QT_TRN("Constant", "Single low-9 quotation mark"),
+ "\u201b" : QT_TRN("Constant", "Single high-reversed-9 quotation mark"),
+ "\u201c" : QT_TRN("Constant", "Left double quotation mark"),
+ "\u201d" : QT_TRN("Constant", "Right double quotation mark"),
+ "\u201e" : QT_TRN("Constant", "Double low-9 quotation mark"),
+ "\u201f" : QT_TRN("Constant", "Double high-reversed-9 quotation mark"),
+ "\u2e42" : QT_TRN("Constant", "Double low-reversed-9 quotation mark"),
- "\u2039" : QT_TRANSLATE_NOOP("Constant", "Single left-pointing angle quotation mark"),
- "\u203a" : QT_TRANSLATE_NOOP("Constant", "Single right-pointing angle quotation mark"),
- "\u00ab" : QT_TRANSLATE_NOOP("Constant", "Left-pointing double angle quotation mark"),
- "\u00bb" : QT_TRANSLATE_NOOP("Constant", "Right-pointing double angle quotation mark"),
+ "\u2039" : QT_TRN("Constant", "Single left-pointing angle quotation mark"),
+ "\u203a" : QT_TRN("Constant", "Single right-pointing angle quotation mark"),
+ "\u00ab" : QT_TRN("Constant", "Left-pointing double angle quotation mark"),
+ "\u00bb" : QT_TRN("Constant", "Right-pointing double angle quotation mark"),
- "\u300c" : QT_TRANSLATE_NOOP("Constant", "Left corner bracket"),
- "\u300d" : QT_TRANSLATE_NOOP("Constant", "Right corner bracket"),
- "\u300e" : QT_TRANSLATE_NOOP("Constant", "Left white corner bracket"),
- "\u300f" : QT_TRANSLATE_NOOP("Constant", "Right white corner bracket"),
+ "\u300c" : QT_TRN("Constant", "Left corner bracket"),
+ "\u300d" : QT_TRN("Constant", "Right corner bracket"),
+ "\u300e" : QT_TRN("Constant", "Left white corner bracket"),
+ "\u300f" : QT_TRN("Constant", "Right white corner bracket"),
}
# END Class nwQuotes
diff --git a/nw/core/document.py b/nw/core/document.py
index 15437ff6..ce91ddd8 100644
--- a/nw/core/document.py
+++ b/nw/core/document.py
@@ -24,10 +24,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from functools import partial
import logging
import os
+from functools import partial
+
from PyQt5.QtCore import QCoreApplication
from nw.constants import nwAlert
@@ -51,7 +52,7 @@ class NWDoc():
# Internal Mapping
self.makeAlert = self.theParent.makeAlert
- self.tr = partial(QCoreApplication.translate, self.__class__.__name__)
+ self.tr = partial(QCoreApplication.translate, "NWDoc")
return
@@ -131,7 +132,9 @@ class NWDoc():
self.theParent.setStatus(
self.tr("{0}: {1}").format(
self.tr("Opened Document"),
- self._theItem.itemName))
+ self._theItem.itemName
+ )
+ )
return theText
@@ -178,7 +181,9 @@ class NWDoc():
self.theParent.setStatus(
self.tr("{0}: {1}").format(
self.tr("Saved Document"),
- self._theItem.itemName))
+ self._theItem.itemName
+ )
+ )
return True
@@ -201,8 +206,9 @@ class NWDoc():
os.unlink(chkFile)
logger.debug("Deleted: %s" % chkFile)
except Exception as e:
- self.makeAlert([self.tr("Could not delete document file."), str(e)],
- nwAlert.ERROR)
+ self.makeAlert(
+ [self.tr("Could not delete document file."), str(e)], nwAlert.ERROR
+ )
return False
return True
diff --git a/nw/core/index.py b/nw/core/index.py
index 9ac2ac45..6af04e3b 100644
--- a/nw/core/index.py
+++ b/nw/core/index.py
@@ -24,13 +24,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from functools import partial
import nw
import logging
import json
import os
from time import time
+from functools import partial
from PyQt5.QtCore import QCoreApplication
@@ -68,10 +68,11 @@ class NWIndex():
self._timeNotes = 0
self._timeIndex = 0
- self.tr = partial(QCoreApplication.translate, self.__class__.__name__)
-
self.clearIndex()
+ # Internal Mappings
+ self.tr = partial(QCoreApplication.translate, "NWIndex")
+
return
##
diff --git a/nw/core/project.py b/nw/core/project.py
index 62cba7ca..8649e978 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -24,9 +24,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from functools import partial
-
-from PyQt5.QtCore import QCoreApplication
import nw
import logging
import os
@@ -34,6 +31,9 @@ import shutil
from lxml import etree
from time import time
+from functools import partial
+
+from PyQt5.QtCore import QCoreApplication
from nw.core.tree import NWTree
from nw.core.item import NWItem
@@ -45,7 +45,7 @@ from nw.common import (
makeFileNameSafe, hexToInt
)
from nw.constants import (
- nwFiles, nwItemType, nwItemClass, nwItemLayout, nwLabels, nwAlert
+ trConst, nwFiles, nwItemType, nwItemClass, nwItemLayout, nwLabels, nwAlert
)
logger = logging.getLogger(__name__)
@@ -102,7 +102,7 @@ class NWProject():
# Internal Mapping
self.makeAlert = self.theParent.makeAlert
- self.tr = partial(QCoreApplication.translate, self.__class__.__name__)
+ self.tr = partial(QCoreApplication.translate, "NWProject")
# Set Defaults
self.clearProject()
@@ -302,8 +302,8 @@ class NWProject():
nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL)
for newRoot in projData.get("addRoots", []):
if newRoot in nwItemClass:
- self.newRoot(QCoreApplication.translate(
- "Constant", nwLabels.CLASS_NAME[newRoot]), newRoot)
+ self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot
+ )
# Create a title page
tHandle = self.newFile(self.tr("Title Page"), nwItemClass.NOVEL, nHandle)
@@ -424,13 +424,15 @@ class NWProject():
# Trying to open backup file instead
backFile = fileName[:-3]+"bak"
if os.path.isfile(backFile):
- self.makeAlert(self.tr("Attempting to open backup project file instead."),
- nwAlert.INFO)
+ self.makeAlert(
+ self.tr("Attempting to open backup project file instead."), nwAlert.INFO
+ )
try:
nwXML = etree.parse(backFile)
except Exception as e:
- self.makeAlert([self.tr("Failed to parse project xml."), str(e)],
- nwAlert.ERROR)
+ self.makeAlert(
+ [self.tr("Failed to parse project xml."), str(e)], nwAlert.ERROR
+ )
self.clearProject()
return False
else:
@@ -477,23 +479,31 @@ class NWProject():
# read the file. Introduced in version 0.10.
if fileVersion == "1.0":
- msgYes = self.theParent.askQuestion(self.tr("Old Project Version"), (
+ msgYes = self.theParent.askQuestion(
+ self.tr("Old Project Version"),
"%s
%s" % (
- self.tr("The project file and data is created by a novelWriter version "
- "lower than 0.7. Do you want to upgrade the project to the "
- "most recent format?"),
- self.tr("Note that after the upgrade, you "
- "cannot open the project with an older version of novelWriter "
- "any more, so make sure you have a recent backup."))))
+ self.tr(
+ "The project file and data is created by a novelWriter version "
+ "lower than 0.7. Do you want to upgrade the project to the "
+ "most recent format?"
+ ),
+ self.tr(
+ "Note that after the upgrade, you cannot open the project with "
+ "an older version of novelWriter any more, so make sure you "
+ "have a recent backup.")
+ )
+ )
if not msgYes:
self.clearProject()
return False
elif fileVersion != "1.1" and fileVersion != "1.2":
self.makeAlert((
- self.tr("Unknown or unsupported novelWriter project file format. "
- "The project cannot be opened by this version of novelWriter. "
- "The file was saved with novelWriter version {0}.").format(appVersion)
+ self.tr(
+ "Unknown or unsupported novelWriter project file format. "
+ "The project cannot be opened by this version of novelWriter. "
+ "The file was saved with novelWriter version {0}."
+ ).format(appVersion)
), nwAlert.ERROR)
self.clearProject()
return False
@@ -502,15 +512,18 @@ class NWProject():
# =========================
if hexToInt(hexVersion) > hexToInt(nw.__hexversion__):
- msgYes = self.theParent.askQuestion(self.tr("Version Conflict"), (
- self.tr("This project was saved by a newer version of novelWriter, version "
- "{new_version}. This is version {version}. If you continue to open the "
- "project, some attributes and settings may not be preserved, but the "
- "overall project should be fine. Continue opening the project?")
- ).format(
- new_version = appVersion,
- version = nw.__version__
- ))
+ msgYes = self.theParent.askQuestion(
+ self.tr("Version Conflict"),
+ self.tr(
+ "This project was saved by a newer version of novelWriter, version "
+ "{new_version}. This is version {version}. If you continue to open the "
+ "project, some attributes and settings may not be preserved, but the "
+ "overall project should be fine. Continue opening the project?"
+ ).format(
+ new_version = appVersion,
+ version = nw.__version__
+ )
+ )
if not msgYes:
self.clearProject()
return False
@@ -610,8 +623,8 @@ class NWProject():
self.mainConf.saveRecentCache()
self.theParent.setStatus(self.tr("{0}: {1}").format(
- self.tr("Opened Project"),
- self.projName))
+ self.tr("Opened Project"), self.projName)
+ )
self._scanProjectFolder()
@@ -731,8 +744,8 @@ class NWProject():
self._writeLockFile()
self.theParent.setStatus(self.tr("{0}: {1}").format(
- self.tr("Saved Project"),
- self.projName))
+ self.tr("Saved Project"), self.projName)
+ )
self.setProjectChanged(False)
return True
@@ -787,24 +800,30 @@ class NWProject():
self.theParent.setStatus(self.tr("Backing up project ..."))
if self.mainConf.backupPath is None or self.mainConf.backupPath == "":
- self.theParent.makeAlert((
- self.tr("Cannot backup project because no backup path is set. "
- "Please set a valid backup location in Tools > Preferences.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "Cannot backup project because no backup path is set. "
+ "Please set a valid backup location in Tools > Preferences."
+ ), nwAlert.ERROR
+ )
return False
if self.projName is None or self.projName == "":
- self.theParent.makeAlert((
- self.tr("Cannot backup project because no project name is set. "
- "Please set a Working Title in Project > Project Settings.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "Cannot backup project because no project name is set. "
+ "Please set a Working Title in Project > Project Settings."
+ ), nwAlert.ERROR
+ )
return False
if not os.path.isdir(self.mainConf.backupPath):
- self.theParent.makeAlert((
- self.tr("Cannot backup project because the backup path does not exist. "
- "Please set a valid backup location in Tools > Preferences.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "Cannot backup project because the backup path does not exist. "
+ "Please set a valid backup location in Tools > Preferences."
+ ), nwAlert.ERROR
+ )
return False
cleanName = makeFileNameSafe(self.projName)
@@ -821,11 +840,13 @@ class NWProject():
return False
if os.path.commonpath([self.projPath, baseDir]) == self.projPath:
- self.theParent.makeAlert((
- self.tr("Cannot backup project because the backup path is within the "
- "project folder to be backed up. Please choose a different "
- "backup path in Tools > Preferences.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "Cannot backup project because the backup path is within the "
+ "project folder to be backed up. Please choose a different "
+ "backup path in Tools > Preferences."
+ ), nwAlert.ERROR
+ )
return False
archName = self.tr("Backup from {0}").format(formatTimeStamp(time(), fileSafe=True))
@@ -838,9 +859,11 @@ class NWProject():
logger.info("Backup written to: %s" % archName)
if doNotify:
self.theParent.makeAlert(
- self.tr("Backup archive file written to: {0}").format(
- f"{os.path.join(cleanName, archName)}.zip"),
- nwAlert.INFO
+ self.tr(
+ "Backup archive file written to: {0}"
+ ).format(
+ f"{os.path.join(cleanName, archName)}.zip"
+ ), nwAlert.INFO
)
except Exception as e:
@@ -865,9 +888,8 @@ class NWProject():
logger.error("No project path set for the example project")
return False
- srcSample = os.path.abspath(os.path.join(self.mainConf.appRoot,
- self.tr("sample")))
- pkgSample = os.path.join(self.mainConf.assetPath, "%s.zip" % self.tr("sample"))
+ srcSample = os.path.abspath(os.path.join(self.mainConf.appRoot, "sample"))
+ pkgSample = os.path.join(self.mainConf.assetPath, "sample.zip")
isSuccess = False
if os.path.isfile(pkgSample):
@@ -889,8 +911,8 @@ class NWProject():
dstProj = os.path.join(projPath, nwFiles.PROJ_FILE)
shutil.copyfile(srcProj, dstProj)
- srcContent = os.path.join(srcSample, self.tr("content"))
- dstContent = os.path.join(projPath, self.tr("content"))
+ srcContent = os.path.join(srcSample, "content")
+ dstContent = os.path.join(projPath, "content")
for srcFile in os.listdir(srcContent):
srcDoc = os.path.join(srcContent, srcFile)
dstDoc = os.path.join(dstContent, srcFile)
@@ -904,10 +926,12 @@ class NWProject():
)
else:
- self.makeAlert((
- self.tr("Failed to create a new example project. Could not find the "
- "necessary files. They seem to be missing from this installation.")
- ), nwAlert.ERROR)
+ self.makeAlert(
+ self.tr(
+ "Failed to create a new example project. Could not find the "
+ "necessary files. They seem to be missing from this installation."
+ ), nwAlert.ERROR
+ )
if isSuccess:
self.clearProject()
@@ -944,10 +968,12 @@ class NWProject():
if os.path.isdir(projPath):
if os.listdir(self.projPath):
- self.theParent.makeAlert((
- self.tr("New project folder is not empty. "
- "Each project requires a dedicated project folder.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "New project folder is not empty. "
+ "Each project requires a dedicated project folder."
+ ), nwAlert.ERROR
+ )
return False
self.ensureFolderStructure()
@@ -994,17 +1020,21 @@ class NWProject():
self.doBackup = doBackup
if doBackup:
if not os.path.isdir(self.mainConf.backupPath):
- self.theParent.makeAlert((
- self.tr("You must set a valid backup path in preferences to use "
- "the automatic project backup feature.")
- ), nwAlert.WARN)
+ self.theParent.makeAlert(
+ self.tr(
+ "You must set a valid backup path in preferences to use "
+ "the automatic project backup feature."
+ ), nwAlert.WARN
+ )
return False
if self.projName == "":
- self.theParent.makeAlert((
- self.tr("You must set a valid project name in project settings to "
- "use the automatic project backup feature.")
- ), nwAlert.WARN)
+ self.theParent.makeAlert(
+ self.tr(
+ "You must set a valid project name in project settings to "
+ "use the automatic project backup feature."
+ ), nwAlert.WARN
+ )
return False
return True
@@ -1354,6 +1384,7 @@ class NWProject():
aDoc = NWDoc(self, self.theParent)
nOrph = 0
noWhere = False
+ oPrefix = self.tr("Recovered")
for oHandle in orphanFiles:
# Look for meta data
@@ -1365,9 +1396,9 @@ class NWProject():
oName, oParent, oClass, oLayout = aDoc.getMeta()
if oName:
- oName = self.tr("{0}: {1}").format(
- self.tr("Recovered"),
- oName.lstrip(self.tr("{0}: ").format(self.tr("Recovered"))))
+ oName = self.tr("[{0}] {1}").format(
+ oPrefix, oName.strip("[%s]" % oPrefix).strip()
+ )
else:
nOrph += 1
oName = self.tr("Recovered File {0}").format(nOrph)
@@ -1397,10 +1428,12 @@ class NWProject():
self.projTree.append(oHandle, oParent, orphItem)
if noWhere:
- self.makeAlert((
- self.tr("One or more orphaned files could not be added back into the "
- "project. Make sure at least a Novel root folder exists.")
- ), nwAlert.WARN)
+ self.makeAlert(
+ self.tr(
+ "One or more orphaned files could not be added back into the "
+ "project. Make sure at least a Novel root folder exists."
+ ), nwAlert.WARN
+ )
return True
@@ -1418,13 +1451,9 @@ class NWProject():
if not isFile:
# It's a new file, so add a header
if self.lastWCount > 0:
- outFile.write("# %s\n" % self.tr("Offset {0}").format(self.lastWCount))
+ outFile.write("# Offset %d\n" % self.lastWCount)
outFile.write("# %-17s %-19s %8s %8s %8s\n" % (
- self.tr("Start Time"),
- self.tr("End Time"),
- self.tr("Novel"),
- self.tr("Notes"),
- self.tr("Idle"),
+ "Start Time", "End Time", "Novel", "Notes", "Idle"
))
outFile.write("%-19s %-19s %8d %8d %8d\n" % (
@@ -1471,10 +1500,12 @@ class NWProject():
newPath = os.path.join(self.projContent, tHandle+".nwd")
try:
os.rename(theFile, newPath)
- logger.info(self.tr("{0}: {1}").format(self.tr("Moved file"), theFile))
- logger.info(self.tr("{0}: {1}").format(self.tr("New location"), newPath))
+ logger.info("Moved file: %s" % theFile)
+ logger.info("New location: %s" % newPath)
except Exception:
- errList.append(self.tr("{0}: {1}").format(self.tr("Could not move"), theFile))
+ errList.append(
+ self.tr("{0}: {1}").format(self.tr("Could not move"), theFile)
+ )
logger.error("Could not move: %s" % theFile)
nw.logException()
@@ -1483,8 +1514,9 @@ class NWProject():
os.unlink(theFile)
logger.info("Deleted file: %s" % theFile)
except Exception:
- errList.append(self.tr("{0}: {1}").format(
- self.tr("Could not delete"), theFile))
+ errList.append(
+ self.tr("{0}: {1}").format(self.tr("Could not delete"), theFile)
+ )
logger.error("Could not delete: %s" % theFile)
nw.logException()
@@ -1499,7 +1531,9 @@ class NWProject():
os.rmdir(theData)
logger.info("Removed folder: %s" % theFolder)
except Exception:
- errList.append(self.tr("{0}: {1}").format(self.tr("Failed to remove"), theFolder))
+ errList.append(
+ self.tr("{0}: {1}").format(self.tr("Failed to remove"), theFolder)
+ )
logger.error("Failed to remove: %s" % theFolder)
nw.logException()
@@ -1509,7 +1543,7 @@ class NWProject():
"""Move an item that doesn't belong in the project folder to
a junk folder.
"""
- theJunk = os.path.join(self.projPath, self.tr("junk"))
+ theJunk = os.path.join(self.projPath, "junk")
if not self._checkFolder(theJunk):
return self.tr("{0}: {1}").format(self.tr("Could not make folder"), theJunk)
@@ -1522,7 +1556,7 @@ class NWProject():
except Exception:
logger.error("Could not move item %s to junk." % theSrc)
nw.logException()
- return self.tr("Could not move item {0} to junk.").format(theSrc)
+ return self.tr("Could not move item {0} to {1}.").format(theSrc, theJunk)
return ""
diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py
index e8500168..04882855 100644
--- a/nw/core/tohtml.py
+++ b/nw/core/tohtml.py
@@ -407,13 +407,11 @@ class ToHtml(Tokenizer):
"""
if self.genMode == self.M_PREVIEW:
return "
\n" % (
- self.tr("Synopsis"),
- tText
+ self._trSynopsis, tText
)
else:
return "%s: %s
\n" % (
- self.tr("Synopsis"),
- tText
+ self._trSynopsis, tText
)
def _formatComments(self, tText):
@@ -422,7 +420,9 @@ class ToHtml(Tokenizer):
if self.genMode == self.M_PREVIEW:
return "\n" % tText
else:
- return "\n" % (self.tr("Comment"), tText)
+ return "\n" % (
+ self._trComment, tText
+ )
def _formatKeywords(self, tText):
"""Apply HTML formatting to keywords.
diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py
index 27136879..d5f4edfc 100644
--- a/nw/core/tokenizer.py
+++ b/nw/core/tokenizer.py
@@ -24,11 +24,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from functools import partial
import logging
import re
from operator import itemgetter
+from functools import partial
+
from PyQt5.QtCore import QCoreApplication, QRegularExpression
from nw.core.document import NWDoc
@@ -142,7 +143,13 @@ class Tokenizer():
# Error Handling
self.errData = []
- self.tr = partial(QCoreApplication.translate, self.__class__.__name__)
+ # Internal Mappings
+ self.tr = partial(QCoreApplication.translate, "Tokenizer")
+
+ # Localisation
+ self._trSynopsis = self.tr("Synopsis")
+ self._trComment = self.tr("Comment")
+ self._trNotes = self.tr("Notes")
return
@@ -252,7 +259,7 @@ class Tokenizer():
if theItem.itemType != nwItemType.ROOT:
return False
- theTitle = self.tr("{0}: {1}").format(self.tr("Notes"), theItem.itemName)
+ theTitle = self.tr("{0}: {1}").format(self._trNotes, theItem.itemName)
self.theTokens = []
self.theTokens.append((
self.T_TITLE, 0, theTitle, None, self.A_PBB | self.A_CENTRE
diff --git a/nw/core/tree.py b/nw/core/tree.py
index d614b4b9..82981969 100644
--- a/nw/core/tree.py
+++ b/nw/core/tree.py
@@ -24,14 +24,14 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-from functools import partial
import nw
import logging
import os
+from time import time
from lxml import etree
from hashlib import sha256
-from time import time
+from functools import partial
from PyQt5.QtCore import QCoreApplication
@@ -82,7 +82,8 @@ class NWTree():
self._handleSeed = None # Used for generating handles for testing
- self.tr = partial(QCoreApplication.translate, self.__class__.__name__)
+ # Internal Mappings
+ self.tr = partial(QCoreApplication.translate, "NWTree")
return
diff --git a/nw/gui/about.py b/nw/gui/about.py
index 33517fb3..f163f934 100644
--- a/nw/gui/about.py
+++ b/nw/gui/about.py
@@ -62,7 +62,7 @@ class GuiAbout(QDialog):
nPx = self.mainConf.pxInt(96)
self.nwIcon = QLabel()
self.nwIcon.setPixmap(self.theParent.theTheme.getPixmap("novelwriter", (nPx, nPx)))
- self.lblName = QLabel("%s" % self.tr("novelWriter"))
+ self.lblName = QLabel("novelWriter")
self.lblVers = QLabel("v%s" % nw.__version__)
self.lblDate = QLabel(datetime.strptime(nw.__date__, "%Y-%m-%d").strftime("%x"))
@@ -136,24 +136,31 @@ class GuiAbout(QDialog):
aboutMsg = "".join([
"%s
" % self.tr("About novelWriter"),
"{copyright:s}.
",
- "%s
" % (self.tr("{0}: {1}").format(
- self.tr("Website"),
- "{domain:s}"
- )),
- "%s
" % self.tr("novelWriter is a markdown-like text editor designed for "
- "organising and writing novels. It is written in Python 3 with "
- "a Qt5 GUI, using PyQt5."),
- "%s
" % self.tr("novelWriter is free software: you can redistribute it and/or "
- "modify it under the terms of the GNU General Public License as "
- "published by the Free Software Foundation, either version 3 of "
- "the License, or (at your option) any later version."),
- "%s
" % self.tr("novelWriter is distributed in the hope that it will be "
- "useful, but WITHOUT ANY WARRANTY; without even the implied "
- "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR "
- "PURPOSE."),
- "%s
" % (self.tr("See the License tab for the full license text, or visit the "
- "GNU website at {0} for more details.").format(
- "GPL v3.0")),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Website"), "{domain:s}"
+ ),
+ "%s
" % self.tr(
+ "novelWriter is a markdown-like text editor designed for organising and "
+ "writing novels. It is written in Python 3 with a Qt5 GUI, using PyQt5."
+ ),
+ "%s
" % self.tr(
+ "novelWriter is free software: you can redistribute it and/or modify it "
+ "under the terms of the GNU General Public License as published by the "
+ "Free Software Foundation, either version 3 of the License, or (at your "
+ "option) any later version."
+ ),
+ "%s
" % self.tr(
+ "novelWriter is distributed in the hope that it will be useful, but "
+ "WITHOUT ANY WARRANTY; without even the implied warranty of "
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ ),
+ "%s
" % (
+ self.tr(
+ "See the License tab for the full license text, or visit the "
+ "GNU website at {0} for more details.").format(
+ "GPL v3.0"
+ )
+ ),
"%s
" % self.tr("Credits"),
"{credits:s}
",
]).format(
@@ -167,49 +174,61 @@ class GuiAbout(QDialog):
theIcons = self.theParent.theTheme.theIcons
if theTheme.themeName:
aboutMsg += "".join([
- ("%s
" % self.tr("{0}: {1}").format(self.tr("Theme"), theTheme.themeName)),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Theme"), theTheme.themeName
+ ),
"",
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Author"), theTheme.themeAuthor)),
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Credit"), theTheme.themeCredit)),
- (self.tr("{0}: {1}").format(
- self.tr("License"),
- "{1}".format(
- theTheme.themeLicenseUrl, theTheme.themeLicense)
- )),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Author"), theTheme.themeAuthor
+ ),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Credit"), theTheme.themeCredit
+ ),
+ self.tr("{0}: {1}").format(
+ self.tr("License"), "{1}".format(
+ theTheme.themeLicenseUrl, theTheme.themeLicense
+ )
+ ),
"
"
])
+
if theIcons.themeName:
aboutMsg += "".join([
- ("%s
" % self.tr("{0}: {1}").format(self.tr("Icons"), theIcons.themeName)),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Icons"), theIcons.themeName
+ ),
"",
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Author"), theIcons.themeAuthor)),
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Credit"), theIcons.themeCredit)),
- (self.tr("{0}: {1}").format(
- self.tr("License"),
- "{1}".format(
- theIcons.themeLicenseUrl, theIcons.themeLicense)
- )),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Author"), theIcons.themeAuthor
+ ),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Credit"), theIcons.themeCredit
+ ),
+ self.tr("{0}: {1}").format(
+ self.tr("License"), "{1}".format(
+ theIcons.themeLicenseUrl, theIcons.themeLicense
+ )
+ ),
"
"
])
+
if theTheme.syntaxName:
aboutMsg += "".join([
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Syntax"),
- theTheme.syntaxName)),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Syntax"), theTheme.syntaxName
+ ),
"",
- ("%s
" % self.tr("{0}: {1}").format(
- self.tr("Author"), theTheme.syntaxAuthor)),
- ("%s
" % self.tr("{0} {1}").format(
- self.tr("Credit"), theTheme.syntaxCredit)),
- (self.tr("{0}: {1}").format(
- self.tr("License"),
- "{1}".format(
- theTheme.syntaxLicenseUrl, theTheme.syntaxLicense)
- )),
+ "%s
" % self.tr("{0}: {1}").format(
+ self.tr("Author"), theTheme.syntaxAuthor
+ ),
+ "%s
" % self.tr("{0} {1}").format(
+ self.tr("Credit"), theTheme.syntaxCredit
+ ),
+ self.tr("{0}: {1}").format(
+ self.tr("License"), "{1}".format(
+ theTheme.syntaxLicenseUrl, theTheme.syntaxLicense
+ )
+ ),
"
"
])
diff --git a/nw/gui/build.py b/nw/gui/build.py
index 33ba23d6..1ddf7b3d 100644
--- a/nw/gui/build.py
+++ b/nw/gui/build.py
@@ -105,7 +105,7 @@ class GuiBuildNovel(QDialog):
self.titleForm = QGridLayout(self)
self.titleGroup.setLayout(self.titleForm)
- fmtHelp = "
".join(
+ fmtHelp = "
".join([
"%s" % self.tr("{0}:").format("Formatting Codes"),
self.tr("{0} for the title as set in the document").format(r"%title%"),
self.tr("{0} for chapter number (1, 2, 3)").format(r"%ch%"),
@@ -114,14 +114,13 @@ class GuiBuildNovel(QDialog):
self.tr("{0} for chapter number in lower case Roman").format(r"%chi%"),
self.tr("{0} for scene number within chapter").format(r"%sc%"),
self.tr("{0} for scene number within novel").format(r"%sca%"),
- )
- fmtScHelp = (
- "
%s" %
- self.tr("Leave blank to skip this heading, or set to a static text, like "
- "for instance '{0}', to make a separator. The separator will "
- "be centred automatically and only appear between sections of "
- "the same type.").format("* * *")
- )
+ ])
+ fmtScHelp = "
%s" % self.tr(
+ "Leave blank to skip this heading, or set to a static text, like "
+ "for instance '{0}', to make a separator. The separator will "
+ "be centred automatically and only appear between sections of "
+ "the same type."
+ ).format("* * *")
xFmt = self.mainConf.pxInt(100)
self.fmtTitle = QLineEdit()
@@ -332,10 +331,10 @@ class GuiBuildNovel(QDialog):
self.fileGroup.setLayout(self.fileForm)
self.novelFiles = QSwitch(width=wS, height=hS)
- self.novelFiles.setToolTip(
- self.tr("Include files with layouts 'Book', 'Page', 'Partition', "
- "'Chapter', 'Unnumbered', and 'Scene'.")
- )
+ self.novelFiles.setToolTip(self.tr(
+ "Include files with layouts 'Book', 'Page', 'Partition', "
+ "'Chapter', 'Unnumbered', and 'Scene'."
+ ))
self.novelFiles.setChecked(
self.optState.getBool("GuiBuildNovel", "addNovel", True)
)
@@ -347,10 +346,10 @@ class GuiBuildNovel(QDialog):
)
self.ignoreFlag = QSwitch(width=wS, height=hS)
- self.ignoreFlag.setToolTip(
- self.tr("Ignore the 'Include when building project' setting and include "
- "all files in the output.")
- )
+ self.ignoreFlag.setToolTip(self.tr(
+ "Ignore the 'Include when building project' setting and include "
+ "all files in the output."
+ ))
self.ignoreFlag.setChecked(
self.optState.getBool("GuiBuildNovel", "ignoreFlag", False)
)
@@ -430,42 +429,51 @@ class GuiBuildNovel(QDialog):
self.btnSave = QPushButton("Save As")
self.btnSave.setMenu(self.saveMenu)
- self.saveODT = QAction(self.tr("{0} ({1})").format(self.tr("Open Document"), ".odt"), self)
+ self.saveODT = QAction(
+ self.tr("{0} ({1})").format(self.tr("Open Document"), ".odt"), self
+ )
self.saveODT.triggered.connect(lambda: self._saveDocument(self.FMT_ODT))
self.saveMenu.addAction(self.saveODT)
self.saveFODT = QAction(
- self.tr("{0} ({1})").format(self.tr("Flat Open Document"), ".fodt"), self)
+ self.tr("{0} ({1})").format(self.tr("Flat Open Document"), ".fodt"), self
+ )
self.saveFODT.triggered.connect(lambda: self._saveDocument(self.FMT_FODT))
self.saveMenu.addAction(self.saveFODT)
- self.saveHTM = QAction(self.tr("{0} ({1})").format(
- self.tr("novelWriter HTML"), ".htm"), self)
+ self.saveHTM = QAction(
+ self.tr("{0} ({1})").format(self.tr("novelWriter HTML"), ".htm"), self
+ )
self.saveHTM.triggered.connect(lambda: self._saveDocument(self.FMT_HTM))
self.saveMenu.addAction(self.saveHTM)
- self.saveNWD = QAction(self.tr("{0} ({1})").format(
- self.tr("novelWriter Markdown"), ".nwd"), self)
+ self.saveNWD = QAction(
+ self.tr("{0} ({1})").format(self.tr("novelWriter Markdown"), ".nwd"), self
+ )
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
self.saveMenu.addAction(self.saveNWD)
self.saveMD = QAction(
- self.tr("{0} ({1})").format(self.tr("Standard Markdown"), ".md"), self)
+ self.tr("{0} ({1})").format(self.tr("Standard Markdown"), ".md"), self
+ )
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
self.saveMenu.addAction(self.saveMD)
self.saveGH = QAction(
- self.tr("{0} ({1})").format(self.tr("GitHub Markdown"), ".md"), self)
+ self.tr("{0} ({1})").format(self.tr("GitHub Markdown"), ".md"), self
+ )
self.saveGH.triggered.connect(lambda: self._saveDocument(self.FMT_GH))
self.saveMenu.addAction(self.saveGH)
- self.saveJsonH = QAction(self.tr("{0} ({1})").format(
- self.tr("JSON + novelWriter HTML"), ".json"), self)
+ self.saveJsonH = QAction(
+ self.tr("{0} ({1})").format(self.tr("JSON + novelWriter HTML"), ".json"), self
+ )
self.saveJsonH.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_H))
self.saveMenu.addAction(self.saveJsonH)
- self.saveJsonM = QAction(self.tr("{0} ({1})").format(
- self.tr("JSON + novelWriters Markdown"), ".json"), self)
+ self.saveJsonM = QAction(
+ self.tr("{0} ({1})").format(self.tr("JSON + novelWriters Markdown"), ".json"), self
+ )
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
self.saveMenu.addAction(self.saveJsonM)
@@ -745,7 +753,8 @@ class GuiBuildNovel(QDialog):
if bldObj.errData:
self.theParent.makeAlert("%s:
- %s" % (
self.tr("There were problems when building the project"),
- "
- ".join(bldObj.errData)), nwAlert.ERROR)
+ "
- ".join(bldObj.errData)), nwAlert.ERROR
+ )
return
@@ -997,14 +1006,14 @@ class GuiBuildNovel(QDialog):
if wSuccess:
self.theParent.makeAlert(
"%s
%s" % (
- self.tr("{0} file successfully written to:").format(textFmt),
- savePath
- ), nwAlert.INFO
+ self.tr("{0} file successfully written to:").format(textFmt), savePath
+ ),
+ nwAlert.INFO
)
else:
self.theParent.makeAlert(
- self.tr("Failed to write {0} file. {1}").format(
- textFmt, errMsg), nwAlert.ERROR
+ self.tr("Failed to write {0} file. {1}").format(textFmt, errMsg),
+ nwAlert.ERROR
)
return wSuccess
@@ -1200,9 +1209,11 @@ class GuiBuildNovelDocView(QTextBrowser):
self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.getTextMargin())
self.setPlaceholderText(
- self.tr("This area will show the content of the document to be "
- "exported or printed. Press the \"Build Preview\" button "
- "to generate content.")
+ self.tr(
+ "This area will show the content of the document to be "
+ "exported or printed. Press the \"Build Preview\" button "
+ "to generate content."
+ )
)
theFont = QFont()
@@ -1234,7 +1245,8 @@ class GuiBuildNovelDocView(QTextBrowser):
fPx = int(1.1*self.theTheme.fontPixelSize)
self.theTitle = QLabel(self.tr("{0}: {1}".format(
- self.tr("Build Time"), self.tr("Unknown"))), self)
+ self.tr("Build Time"), self.tr("Unknown"))), self
+ )
self.theTitle.setIndent(0)
self.theTitle.setAutoFillBackground(True)
self.theTitle.setAlignment(Qt.AlignCenter)
@@ -1349,8 +1361,12 @@ class GuiBuildNovelDocView(QTextBrowser):
)
else:
strBuildTime = self.tr("Unknown")
+
self.theTitle.setText(self.tr("{0}: {1}").format(
- self.tr("Build Time"), strBuildTime))
+ self.tr("Build Time"), strBuildTime)
+ )
+
+ return
def _updateDocMargins(self):
"""Automatically adjust the header to fill the top of the
diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py
index f9db730a..7adccb4a 100644
--- a/nw/gui/doceditor.py
+++ b/nw/gui/doceditor.py
@@ -36,7 +36,7 @@ import logging
from time import time
from PyQt5.QtCore import (
- QCoreApplication, Qt, QSize, QTimer, pyqtSlot, pyqtSignal, QRegExp, QRegularExpression,
+ Qt, QSize, QTimer, pyqtSlot, pyqtSignal, QRegExp, QRegularExpression,
QPointF, QObject, QRunnable, QPropertyAnimation
)
from PyQt5.QtGui import (
@@ -53,8 +53,8 @@ from nw.core import NWDoc, NWSpellSimple, countWords
from nw.gui.dochighlight import GuiDocHighlighter
from nw.common import transferCase
from nw.constants import (
- nwConst, nwAlert, nwUnicode, nwDocAction, nwDocInsert, nwItemClass,
- nwKeyWords, nwLabels
+ trConst, nwConst, nwAlert, nwUnicode, nwDocAction, nwDocInsert,
+ nwItemClass, nwKeyWords, nwLabels
)
logger = logging.getLogger(__name__)
@@ -293,15 +293,17 @@ class GuiDocEditor(QTextEdit):
docSize = len(theDoc)
if docSize > nwConst.MAX_DOCSIZE:
- self.theParent.makeAlert((
- self.tr("The document you are trying to open is too big. "
- "The document size is {doc_size}. "
- "The maximum size allowed is {max_size}.").
- format(
+ self.theParent.makeAlert(
+ self.tr(
+ "The document you are trying to open is too big. "
+ "The document size is {doc_size}. "
+ "The maximum size allowed is {max_size}."
+ ).format(
doc_size=self.tr("{0}\u202fMB").format(f"{docSize/1.0e6:.2f}"),
max_size=self.tr("{0}\u202fMB").format(f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}")
- )
- ), nwAlert.ERROR)
+ ),
+ nwAlert.ERROR
+ )
self.clearEditor()
return False
@@ -384,15 +386,17 @@ class GuiDocEditor(QTextEdit):
"""
docSize = len(theText)
if docSize > nwConst.MAX_DOCSIZE:
- self.theParent.makeAlert((
- self.tr("The text you are trying to add is too big. "
- "The text size is {text_size}. "
- "The maximum size allowed is {max_size}.").
- format(
+ self.theParent.makeAlert(
+ self.tr(
+ "The text you are trying to add is too big. "
+ "The text size is {text_size}. "
+ "The maximum size allowed is {max_size}."
+ ).format(
text_size=self.tr("{0}\u202fMB").format(f"{docSize/1.0e6:.2f}"),
max_size=self.tr("{0}\u202fMB").format(f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}")
- )
- ), nwAlert.ERROR)
+ ),
+ nwAlert.ERROR
+ )
return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
@@ -747,15 +751,14 @@ class GuiDocEditor(QTextEdit):
return False
msgBox = QMessageBox()
- msgBox.information(self, self.tr("File Location"), "".join([
- (self.tr("{0}
").format(self.tr("File details for the currently open file"))),
- (self.tr("{0}
").format(
- self.tr("{0}: {1}").format(self.tr("Handle"), "{handle:s}"))),
- (self.tr("{0}: {1}").format(self.tr("Location"), "{fileLoc:s}"))
- ]).format(
- handle = self.theHandle,
- fileLoc = str(self.nwDocument.getFileLocation())
- ))
+ msgBox.information(
+ self,
+ self.tr("File Location"),
+ "%s
%s" % (
+ self.tr("The currently open file is saved in:"),
+ self.nwDocument.getFileLocation()
+ ),
+ )
return
@@ -938,11 +941,15 @@ class GuiDocEditor(QTextEdit):
self.lastFind = None
if self.qDocument.characterCount() > nwConst.MAX_DOCSIZE:
- self.theParent.makeAlert((
- self.tr("The document has grown too big and you cannot add more text to it. "
- "The maximum size of a single novelWriter document is {max_size}.").
- format(max_size=self.tr("{0}\u202fMB").format(f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"))
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "The document has grown too big and you cannot add more text to it. "
+ "The maximum size of a single novelWriter document is {max_size}."
+ ).format(
+ max_size=self.tr("{0}\u202fMB").format(f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}")
+ ),
+ nwAlert.ERROR
+ )
self.undo()
return
@@ -1860,8 +1867,7 @@ class GuiDocEditSearch(QFrame):
self.searchOpt.addAction(self.toggleWord)
self.toggleRegEx = QAction(self.tr("RegEx Mode"), self)
- self.toggleRegEx.setToolTip(self.tr("Use regular expressions (requires Qt {0})").format(
- "5.3"))
+ self.toggleRegEx.setToolTip(self.tr("Search using regular expressions"))
self.toggleRegEx.setIcon(self.theTheme.getIcon("search_regex"))
self.toggleRegEx.setCheckable(True)
self.toggleRegEx.setChecked(self.isRegEx)
@@ -2541,10 +2547,8 @@ class GuiDocEditFooter(QWidget):
theIcon = self.theParent.importIcons[iStatus]
sIcon = theIcon.pixmap(self.sPx, self.sPx)
- sClass = QCoreApplication.translate(
- "Constant", nwLabels.CLASS_NAME[self.theItem.itemClass])
- sLayout = QCoreApplication.translate(
- "Constant", nwLabels.LAYOUT_NAME[self.theItem.itemLayout])
+ sClass = trConst(nwLabels.CLASS_NAME[self.theItem.itemClass])
+ sLayout = trConst(nwLabels.LAYOUT_NAME[self.theItem.itemLayout])
sText = f"{self.theItem.itemStatus} / {sClass} / {sLayout}"
self.statusIcon.setPixmap(sIcon)
@@ -2565,7 +2569,9 @@ class GuiDocEditFooter(QWidget):
self.linesText.setText(
self.tr("{0}: {1} ({2}\u202f%%)".format(
- self.tr("Line"), f"{iLine:n}", f"{iDist:.0f}")))
+ self.tr("Line"), f"{iLine:n}", f"{iDist:.0f}")
+ )
+ )
return
@@ -2581,11 +2587,14 @@ class GuiDocEditFooter(QWidget):
self.wordsText.setText(
self.tr("{0}: {1} ({2})".format(
- self.tr("Words"), f"{wCount:n}", f"{wDiff:+n}")))
+ self.tr("Words"), f"{wCount:n}", f"{wDiff:+n}")
+ )
+ )
byteSize = self.docEditor.qDocument.characterCount()
self.wordsText.setToolTip(
- (self.tr("Document size is {0} bytes").format(f"{byteSize:n}")))
+ self.tr("Document size is {0} bytes").format(f"{byteSize:n}")
+ )
return
diff --git a/nw/gui/docmerge.py b/nw/gui/docmerge.py
index c62bd5d1..2d2c8887 100644
--- a/nw/gui/docmerge.py
+++ b/nw/gui/docmerge.py
@@ -104,9 +104,9 @@ class GuiDocMerge(QDialog):
finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
if len(finalOrder) == 0:
- self.theParent.makeAlert((
- self.tr("No source documents found. Nothing to do.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("No source documents found. Nothing to do."), nwAlert.ERROR
+ )
return
theDoc = NWDoc(self.theProject, self.theParent)
@@ -116,16 +116,16 @@ class GuiDocMerge(QDialog):
theText += "\n\n"
if self.sourceItem is None:
- self.theParent.makeAlert((
- self.tr("No source document selected. Nothing to do.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("No source document selected. Nothing to do."), nwAlert.ERROR
+ )
return
srcItem = self.theProject.projTree[self.sourceItem]
if srcItem is None:
- self.theParent.makeAlert((
- self.tr("Could not parse source document.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("Could not parse source document."), nwAlert.ERROR
+ )
return
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.itemParent)
@@ -166,9 +166,9 @@ class GuiDocMerge(QDialog):
if nwItem is None:
return
if nwItem.itemType is not nwItemType.FOLDER:
- self.theParent.makeAlert((
- self.tr("Element selected in the project tree must be a folder.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("Element selected in the project tree must be a folder."), nwAlert.ERROR
+ )
return
for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle):
diff --git a/nw/gui/docsplit.py b/nw/gui/docsplit.py
index ae611b4b..b72f9b3c 100644
--- a/nw/gui/docsplit.py
+++ b/nw/gui/docsplit.py
@@ -118,16 +118,16 @@ class GuiDocSplit(QDialog):
logger.verbose("GuiDocSplit split button clicked")
if self.sourceItem is None:
- self.theParent.makeAlert((
- self.tr("No source document selected. Nothing to do.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("No source document selected. Nothing to do."), nwAlert.ERROR
+ )
return
srcItem = self.theProject.projTree[self.sourceItem]
if srcItem is None:
- self.theParent.makeAlert((
- self.tr("Could not parse source document.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("Could not parse source document."), nwAlert.ERROR
+ )
return
theDoc = NWDoc(self.theProject, self.theParent)
@@ -150,26 +150,34 @@ class GuiDocSplit(QDialog):
nFiles = len(finalOrder)
if nFiles == 0:
- self.theParent.makeAlert((
- self.tr("No headers found. Nothing to do.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("No headers found. Nothing to do."), nwAlert.ERROR
+ )
return
# Check that another folder can be created
parTree = self.theProject.projTree.getItemPath(srcItem.itemParent)
if len(parTree) >= nwConst.MAX_DEPTH - 1:
- self.theParent.makeAlert((
- self.tr("Cannot add new folder for the document split. "
- "Maximum folder depth has been reached. "
- "Please move the file to another level in the project tree.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr(
+ "Cannot add new folder for the document split. "
+ "Maximum folder depth has been reached. "
+ "Please move the file to another level in the project tree."
+ ), nwAlert.ERROR
+ )
return
- msgYes = self.theParent.askQuestion(self.tr("Split Document"), "%s
%s" % (
- self.tr("The document will be split into {0} file(s) in a new folder. "
- "The original document will remain intact.", n=nFiles).format(nFiles),
- self.tr("Continue with the splitting process?")
- ))
+ msgYes = self.theParent.askQuestion(
+ self.tr("Split Document"),
+ "%s
%s" % (
+ self.tr(
+ "The document will be split into {0} file(s) in a new folder. "
+ "The original document will remain intact.").format(nFiles),
+ self.tr(
+ "Continue with the splitting process?"
+ )
+ )
+ )
if not msgYes:
return
@@ -245,9 +253,9 @@ class GuiDocSplit(QDialog):
if nwItem is None:
return
if nwItem.itemType is not nwItemType.FILE:
- self.theParent.makeAlert((
- self.tr("Element selected in the project tree must be a file.")
- ), nwAlert.ERROR)
+ self.theParent.makeAlert(
+ self.tr("Element selected in the project tree must be a file."), nwAlert.ERROR
+ )
return
self.listBox.clear()
diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py
index 0b34ebeb..33c5a6da 100644
--- a/nw/gui/docviewer.py
+++ b/nw/gui/docviewer.py
@@ -244,10 +244,13 @@ class GuiDocViewer(QTextBrowser):
tHandle, _, sTitle = self.theParent.theIndex.getTagSource(theTag)
if tHandle is None:
self.theParent.makeAlert(
- self.tr("Could not find the reference for tag '{0}'. It either doesn't "
- "exist, or the index is out of date. The index can be updated "
- "from the Tools menu, or by pressing {1}.").
- format(theTag, "F9"), nwAlert.ERROR)
+ self.tr(
+ "Could not find the reference for tag '{0}'. It either doesn't "
+ "exist, or the index is out of date. The index can be updated "
+ "from the Tools menu, or by pressing {1}."
+ ).format(theTag, "F9"),
+ nwAlert.ERROR
+ )
return False
else:
# Let the parent handle the opening as it also ensures that
@@ -956,8 +959,9 @@ class GuiDocViewFooter(QWidget):
self.stickyRefs.setFixedSize(QSize(fPx, fPx))
self.stickyRefs.toggled.connect(self._doToggleSticky)
self.stickyRefs.setToolTip(
- self.tr("Activate to freeze the content of the references panel when "
- "changing document")
+ self.tr(
+ "Activate to freeze the content of the references panel when changing document"
+ )
)
# Show Comments
diff --git a/nw/gui/itemdetails.py b/nw/gui/itemdetails.py
index ec77b2c9..608aa6ba 100644
--- a/nw/gui/itemdetails.py
+++ b/nw/gui/itemdetails.py
@@ -27,12 +27,12 @@ along with this program. If not, see .
import nw
import logging
-from PyQt5.QtCore import QCoreApplication, Qt
+from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QPixmap
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel
from nw.constants import (
- nwLabels, nwItemClass, nwItemType, nwItemLayout
+ trConst, nwLabels, nwItemClass, nwItemType, nwItemLayout
)
logger = logging.getLogger(__name__)
@@ -118,7 +118,7 @@ class GuiItemDetails(QWidget):
self.layoutData.setAlignment(Qt.AlignLeft)
# Character Count
- self.cCountName = QLabel(self.tr(" Characters"))
+ self.cCountName = QLabel(" "+self.tr("Characters"))
self.cCountName.setFont(self.fntLabel)
self.cCountName.setAlignment(Qt.AlignRight)
@@ -127,7 +127,7 @@ class GuiItemDetails(QWidget):
self.cCountData.setAlignment(Qt.AlignRight)
# Word Count
- self.wCountName = QLabel(self.tr(" Words"))
+ self.wCountName = QLabel(" "+self.tr("Words"))
self.wCountName.setFont(self.fntLabel)
self.wCountName.setAlignment(Qt.AlignRight)
@@ -136,7 +136,7 @@ class GuiItemDetails(QWidget):
self.wCountData.setAlignment(Qt.AlignRight)
# Paragraph Count
- self.pCountName = QLabel(self.tr(" Paragraphs"))
+ self.pCountName = QLabel(" "+self.tr("Paragraphs"))
self.pCountName.setFont(self.fntLabel)
self.pCountName.setAlignment(Qt.AlignRight)
@@ -268,10 +268,8 @@ class GuiItemDetails(QWidget):
self.labelData.setText(theLabel)
self.statusData.setText(nwItem.itemStatus)
- self.classData.setText(QCoreApplication.translate(
- "Constant", nwLabels.CLASS_NAME[nwItem.itemClass]))
- self.layoutData.setText(QCoreApplication.translate(
- "Constant", nwLabels.LAYOUT_NAME[nwItem.itemLayout]))
+ self.classData.setText(trConst(nwLabels.CLASS_NAME[nwItem.itemClass]))
+ self.layoutData.setText(trConst(nwLabels.LAYOUT_NAME[nwItem.itemLayout]))
if nwItem.itemType == nwItemType.FILE:
self.cCountData.setText(f"{nwItem.charCount:n}")
diff --git a/nw/gui/itemeditor.py b/nw/gui/itemeditor.py
index 37154d86..107172f0 100644
--- a/nw/gui/itemeditor.py
+++ b/nw/gui/itemeditor.py
@@ -27,14 +27,14 @@ along with this program. If not, see .
import nw
import logging
-from PyQt5.QtCore import QCoreApplication, pyqtSlot
+from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
QDialogButtonBox
)
from nw.gui.custom import QSwitch
-from nw.constants import nwLabels, nwItemLayout, nwItemType, nwLists
+from nw.constants import trConst, nwLabels, nwItemLayout, nwItemType, nwLists
logger = logging.getLogger(__name__)
@@ -103,8 +103,7 @@ class GuiItemEditor(QDialog):
for itemLayout in nwItemLayout:
if itemLayout in validLayouts:
- self.editLayout.addItem(QCoreApplication.translate(
- "Constant", nwLabels.LAYOUT_NAME[itemLayout]), itemLayout)
+ self.editLayout.addItem(trConst(nwLabels.LAYOUT_NAME[itemLayout]), itemLayout)
# Export Switch
self.textExport = QLabel(self.tr("Include when building project"))
@@ -139,17 +138,21 @@ class GuiItemEditor(QDialog):
# Assemble
##
+ nameLabel = QLabel(self.tr("Label"))
+ statusLabel = QLabel(self.tr("Status"))
+ layoutLabel = QLabel(self.tr("Layout"))
+
self.mainForm = QGridLayout()
self.mainForm.setVerticalSpacing(vSp)
self.mainForm.setHorizontalSpacing(mSp)
- self.mainForm.addWidget(QLabel(self.tr("Label")), 0, 0, 1, 1)
- self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
- self.mainForm.addWidget(QLabel(self.tr("Status")), 1, 0, 1, 1)
- self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
- self.mainForm.addWidget(QLabel(self.tr("Layout")), 2, 0, 1, 1)
- self.mainForm.addWidget(self.editLayout, 2, 1, 1, 2)
- self.mainForm.addWidget(self.textExport, 3, 0, 1, 2)
- self.mainForm.addWidget(self.editExport, 3, 2, 1, 1)
+ self.mainForm.addWidget(nameLabel, 0, 0, 1, 1)
+ self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
+ self.mainForm.addWidget(statusLabel, 1, 0, 1, 1)
+ self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
+ self.mainForm.addWidget(layoutLabel, 2, 0, 1, 1)
+ self.mainForm.addWidget(self.editLayout, 2, 1, 1, 2)
+ self.mainForm.addWidget(self.textExport, 3, 0, 1, 2)
+ self.mainForm.addWidget(self.editExport, 3, 2, 1, 1)
self.mainForm.setColumnStretch(0, 0)
self.mainForm.setColumnStretch(1, 1)
self.mainForm.setColumnStretch(2, 0)
diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py
index dd2da1bd..184289f8 100644
--- a/nw/gui/mainmenu.py
+++ b/nw/gui/mainmenu.py
@@ -27,13 +27,13 @@ along with this program. If not, see .
import nw
import logging
-from PyQt5.QtCore import QCoreApplication, QUrl, QProcess
+from PyQt5.QtCore import QUrl, QProcess
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QMenuBar, QAction
from nw.constants import (
- nwItemType, nwItemClass, nwDocAction, nwDocInsert, nwKeyWords, nwLabels,
- nwUnicode
+ trConst, nwItemType, nwItemClass, nwDocAction, nwDocInsert, nwKeyWords,
+ nwLabels, nwUnicode
)
logger = logging.getLogger(__name__)
@@ -566,7 +566,8 @@ class GuiMainMenu(QMenuBar):
# Insert > Figure Dash
self.aInsFigDash = QAction(self.tr("Figure Dash"), self)
self.aInsFigDash.setStatusTip(
- self.tr("Insert figure dash (same width as a number character)"))
+ self.tr("Insert figure dash (same width as a number character)")
+ )
self.aInsFigDash.setShortcut("Ctrl+K, ~")
self.aInsFigDash.triggered.connect(lambda: self._docInsert(nwUnicode.U_FGDASH))
self.mInsDashes.addAction(self.aInsFigDash)
@@ -740,8 +741,7 @@ class GuiMainMenu(QMenuBar):
self.mInsKWItems[nwKeyWords.ENTITY_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, E")
self.mInsKWItems[nwKeyWords.CUSTOM_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, X")
for n, keyWord in enumerate(self.mInsKWItems):
- self.mInsKWItems[keyWord][0].setText(
- QCoreApplication.translate("Constant", nwLabels.KEY_NAME[keyWord]))
+ self.mInsKWItems[keyWord][0].setText(trConst(nwLabels.KEY_NAME[keyWord]))
self.mInsKWItems[keyWord][0].setShortcut(self.mInsKWItems[keyWord][1])
self.mInsKWItems[keyWord][0].triggered.connect(
lambda n, keyWord=keyWord: self._insertKeyWord(keyWord)
@@ -796,7 +796,8 @@ class GuiMainMenu(QMenuBar):
# Search > Replace Next
self.aReplaceNext = QAction(self.tr("Replace Next"), self)
self.aReplaceNext.setStatusTip(
- self.tr("Find and replace next occurrence text in document"))
+ self.tr("Find and replace next occurrence text in document")
+ )
self.aReplaceNext.setShortcut("Ctrl+Shift+1")
self.aReplaceNext.triggered.connect(lambda: self._docAction(nwDocAction.REPL_NEXT))
self.srcMenu.addAction(self.aReplaceNext)
@@ -898,14 +899,16 @@ class GuiMainMenu(QMenuBar):
# Format > Replace Single Quotes
self.aFmtReplSng = QAction(self.tr("Replace Single Quotes"), self)
self.aFmtReplSng.setStatusTip(
- self.tr("Replace all straight single quotes in selected text"))
+ self.tr("Replace all straight single quotes in selected text")
+ )
self.aFmtReplSng.triggered.connect(lambda: self._docAction(nwDocAction.REPL_SNG))
self.fmtMenu.addAction(self.aFmtReplSng)
# Format > Replace Double Quotes
self.aFmtReplDbl = QAction(self.tr("Replace Double Quotes"), self)
self.aFmtReplDbl.setStatusTip(
- self.tr("Replace all straight double quotes in selected text"))
+ self.tr("Replace all straight double quotes in selected text")
+ )
self.aFmtReplDbl.triggered.connect(lambda: self._docAction(nwDocAction.REPL_DBL))
self.fmtMenu.addAction(self.aFmtReplDbl)
@@ -1031,7 +1034,8 @@ class GuiMainMenu(QMenuBar):
self.aHelpWeb = QAction(self.tr("Documentation (Online)"), self)
self.aHelpWeb.setStatusTip(
- self.tr("View online documentation at {0}").format(nw.__docurl__))
+ self.tr("View online documentation at {0}").format(nw.__docurl__)
+ )
self.aHelpWeb.triggered.connect(lambda: self._openWebsite(nw.__docurl__))
if self.mainConf.hasHelp and self.mainConf.hasAssistant:
self.aHelpWeb.setShortcut("Shift+F1")
@@ -1045,28 +1049,32 @@ class GuiMainMenu(QMenuBar):
# Document > Report an Issue
self.aIssue = QAction(self.tr("Report an Issue (GitHub)"), self)
self.aIssue.setStatusTip(
- self.tr("Report a bug or issue on GitHub at {0}").format(nw.__issuesurl__))
+ self.tr("Report a bug or issue on GitHub at {0}").format(nw.__issuesurl__)
+ )
self.aIssue.triggered.connect(lambda: self._openWebsite(nw.__issuesurl__))
self.helpMenu.addAction(self.aIssue)
# Document > Ask a Question
self.aQuestion = QAction(self.tr("Ask a Question (GitHub)"), self)
self.aQuestion.setStatusTip(
- self.tr("Ask a question on GitHub at {0}").format(nw.__helpurl__))
+ self.tr("Ask a question on GitHub at {0}").format(nw.__helpurl__)
+ )
self.aQuestion.triggered.connect(lambda: self._openWebsite(nw.__helpurl__))
self.helpMenu.addAction(self.aQuestion)
# Document > Latest Release
self.aRelease = QAction(self.tr("Latest Release (GitHub)"), self)
self.aRelease.setStatusTip(
- self.tr("Open the Releases page on GitHub at {0}").format(nw.__releaseurl__))
+ self.tr("Open the Releases page on GitHub at {0}").format(nw.__releaseurl__)
+ )
self.aRelease.triggered.connect(lambda: self._openWebsite(nw.__releaseurl__))
self.helpMenu.addAction(self.aRelease)
# Document > Main Website
self.aWebsite = QAction(self.tr("The novelWriter Website"), self)
self.aWebsite.setStatusTip(
- self.tr("Open the novelWriter website at {0}").format(nw.__url__))
+ self.tr("Open the novelWriter website at {0}").format(nw.__url__)
+ )
self.aWebsite.triggered.connect(lambda: self._openWebsite(nw.__url__))
self.helpMenu.addAction(self.aWebsite)
diff --git a/nw/gui/outline.py b/nw/gui/outline.py
index fac7de53..7a54c6be 100644
--- a/nw/gui/outline.py
+++ b/nw/gui/outline.py
@@ -29,12 +29,12 @@ import logging
from time import time
-from PyQt5.QtCore import QCoreApplication, Qt, QSize
+from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QMenu, QAction, QAbstractItemView
)
-from nw.constants import nwKeyWords, nwLabels, nwOutline
+from nw.constants import trConst, nwKeyWords, nwLabels, nwOutline
logger = logging.getLogger(__name__)
@@ -149,8 +149,7 @@ class GuiOutline(QTreeWidget):
"""
self.clear()
self.setColumnCount(1)
- self.setHeaderLabel(
- QCoreApplication.translate("Constant", nwLabels.OUTLINE_COLS[nwOutline.TITLE]))
+ self.setHeaderLabel(trConst(nwLabels.OUTLINE_COLS[nwOutline.TITLE]))
self.treeOrder = []
self.colWidth = {}
@@ -356,8 +355,7 @@ class GuiOutline(QTreeWidget):
if self.firstView:
theLabels = []
for i, hItem in enumerate(self.treeOrder):
- theLabels.append(
- QCoreApplication.translate("Constant", nwLabels.OUTLINE_COLS[hItem]))
+ theLabels.append(trConst(nwLabels.OUTLINE_COLS[hItem]))
self.colIndex[hItem] = i
self.setHeaderLabels(theLabels)
@@ -484,8 +482,7 @@ class GuiOutlineHeaderMenu(QMenu):
for hItem in nwOutline:
if hItem == nwOutline.TITLE:
continue
- self.actionMap[hItem] = QAction(
- QCoreApplication.translate("Constant", nwLabels.OUTLINE_COLS[hItem]), self)
+ self.actionMap[hItem] = QAction(trConst(nwLabels.OUTLINE_COLS[hItem]), self)
self.actionMap[hItem].setCheckable(True)
self.actionMap[hItem].toggled.connect(
lambda isChecked, tItem=hItem : self._columnToggled(isChecked, tItem)
diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py
index ab83ccee..d5ba010a 100644
--- a/nw/gui/outlinedetails.py
+++ b/nw/gui/outlinedetails.py
@@ -27,12 +27,13 @@ along with this program. If not, see .
import nw
import logging
-from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP, Qt
+from PyQt5.QtCore import Qt
+from PyQt5.QtCore import QT_TRANSLATE_NOOP as QT_TRN
from PyQt5.QtWidgets import (
QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel
)
-from nw.constants import nwLabels, nwKeyWords
+from nw.constants import trConst, nwLabels, nwKeyWords
from nw.common import checkInt
logger = logging.getLogger(__name__)
@@ -40,10 +41,10 @@ logger = logging.getLogger(__name__)
class GuiOutlineDetails(QScrollArea):
LVL_MAP = {
- "H1" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Title"),
- "H2" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Chapter"),
- "H3" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Scene"),
- "H4" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Section"),
+ "H1" : QT_TRN("GuiOutlineDetails", "Title"),
+ "H2" : QT_TRN("GuiOutlineDetails", "Chapter"),
+ "H3" : QT_TRN("GuiOutlineDetails", "Scene"),
+ "H4" : QT_TRN("GuiOutlineDetails", "Section"),
}
def __init__(self, theParent):
@@ -104,24 +105,15 @@ class GuiOutlineDetails(QScrollArea):
self.synopLWrap.addWidget(self.synopValue, 1)
# Tags
- self.povKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
- self.focKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
- self.chrKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
- self.pltKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
- self.timKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
- self.wldKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
- self.objKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
- self.entKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
- self.cstKeyLabel = QLabel("%s" % QCoreApplication.translate(
- "Constant", nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
+ self.povKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
+ self.focKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
+ self.chrKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
+ self.pltKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
+ self.timKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
+ self.wldKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
+ self.objKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
+ self.entKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
+ self.cstKeyLabel = QLabel("%s" % trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
self.povKeyLWrap = QHBoxLayout()
self.focKeyLWrap = QHBoxLayout()
diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py
index 9e7e1029..cccdc6c9 100644
--- a/nw/gui/projdetails.py
+++ b/nw/gui/projdetails.py
@@ -155,8 +155,11 @@ class GuiProjectDetailsMain(QWidget):
self.bookTitle.setAlignment(Qt.AlignHCenter)
self.bookTitle.setWordWrap(True)
- self.projName = QLabel(self.tr("{0}: {1}").format(
- self.tr("Working Title"), self.theProject.projName))
+ self.projName = QLabel(
+ self.tr("{0}: {1}").format(
+ self.tr("Working Title"), self.theProject.projName
+ )
+ )
workFont = self.projName.font()
workFont.setPointSizeF(0.8*fPt)
workFont.setItalic(True)
@@ -273,13 +276,14 @@ class GuiProjectDetailsContents(QWidget):
self.tocTree.setIndentation(0)
self.tocTree.setColumnCount(6)
self.tocTree.setSelectionMode(QAbstractItemView.NoSelection)
- self.tocTree.setHeaderLabels(
- [self.tr("Title"),
- self.tr("Words"),
- self.tr("Pages"),
- self.tr("Page"),
- self.tr("Progress"),
- ""])
+ self.tocTree.setHeaderLabels([
+ self.tr("Title"),
+ self.tr("Words"),
+ self.tr("Pages"),
+ self.tr("Page"),
+ self.tr("Progress"),
+ ""
+ ])
treeHeadItem = self.tocTree.headerItem()
treeHeadItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
diff --git a/nw/gui/projload.py b/nw/gui/projload.py
index 8579d194..118a1ba8 100644
--- a/nw/gui/projload.py
+++ b/nw/gui/projload.py
@@ -192,7 +192,8 @@ class GuiProjectLoad(QDialog):
self, self.tr("Open novelWriter Project"), "",
";;".join([
self.tr("{0} ({1})").format(
- self.tr("novelWriter Project File"), nwFiles.PROJ_FILE),
+ self.tr("novelWriter Project File"), nwFiles.PROJ_FILE
+ ),
self.tr("{0} ({1})").format(self.tr("All Files"), "*")
]),
options=dlgOpt
@@ -233,8 +234,10 @@ class GuiProjectLoad(QDialog):
projName = selList[0].text(self.C_NAME)
msgYes = self.theParent.askQuestion(
self.tr("Remove Entry"),
- self.tr("Remove '{0}' from the recent projects list? "
- "The project files will not be deleted.").format(projName)
+ self.tr(
+ "Remove '{0}' from the recent projects list? "
+ "The project files will not be deleted."
+ ).format(projName)
)
if msgYes:
self.mainConf.removeFromRecentCache(
diff --git a/nw/gui/projsettings.py b/nw/gui/projsettings.py
index 71cc7043..4a3a6898 100644
--- a/nw/gui/projsettings.py
+++ b/nw/gui/projsettings.py
@@ -378,7 +378,8 @@ class GuiProjectEditStatus(QWidget):
self.colData[selIdx][4]
)
selItem.setText(self.tr("{0} [{1}]").format(
- self.colData[selIdx][0], self.colCounts[selIdx]))
+ self.colData[selIdx][0], self.colCounts[selIdx])
+ )
selItem.setIcon(self.colButton.icon())
self.editName.setEnabled(False)
self.colChanged = True
@@ -496,7 +497,8 @@ class GuiProjectEditReplace(QWidget):
self.bottomBox.addWidget(self.delButton)
self.outerBox.addWidget(
- QLabel("%s" % self.tr("Text Replace List for Preview and Export")))
+ QLabel("%s" % self.tr("Text Replace List for Preview and Export"))
+ )
self.outerBox.addWidget(self.listBox)
self.outerBox.addLayout(self.bottomBox)
self.setLayout(self.outerBox)
@@ -548,7 +550,7 @@ class GuiProjectEditReplace(QWidget):
saveKey = self._stripNotAllowed(newKey)
if len(saveKey) > 0 and len(newVal) > 0:
- selItem.setText(0, self.tr("<{0}>").format(saveKey))
+ selItem.setText(0, "<%s>" % saveKey)
selItem.setText(1, newVal)
self.editKey.clear()
self.editValue.clear()
diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py
index 02b8228c..a9d08ed1 100644
--- a/nw/gui/projtree.py
+++ b/nw/gui/projtree.py
@@ -30,7 +30,7 @@ import logging
from time import time
-from PyQt5.QtCore import QCoreApplication, Qt, QSize, pyqtSignal
+from PyQt5.QtCore import Qt, QSize, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction
@@ -38,7 +38,8 @@ from PyQt5.QtWidgets import (
from nw.core import NWDoc
from nw.constants import (
- nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwConst, nwLists
+ trConst, nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert,
+ nwConst, nwLists
)
logger = logging.getLogger(__name__)
@@ -214,8 +215,7 @@ class GuiProjectTree(QTreeWidget):
)
if itemType == nwItemType.ROOT:
- tHandle = self.theProject.newRoot(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[itemClass]), itemClass)
+ tHandle = self.theProject.newRoot(trConst(nwLabels.CLASS_NAME[itemClass]), itemClass)
if tHandle is None:
logger.error("No root item added")
return False
@@ -250,8 +250,7 @@ class GuiProjectTree(QTreeWidget):
if self.theProject.projTree.isTrashRoot(pHandle):
self.makeAlert(
self.tr("Cannot add new files or folders to the {0} folder.").format(
- QCoreApplication.translate(
- "Constant", nwLabels.CLASS_NAME[nwItemClass.TRASH])
+ trConst(nwLabels.CLASS_NAME[nwItemClass.TRASH])
), nwAlert.ERROR
)
return False
@@ -573,10 +572,10 @@ class GuiProjectTree(QTreeWidget):
self._deleteTreeItem(tHandle)
self._setTreeChanged(True)
else:
- self.makeAlert((
- self.tr("Cannot delete folder. It is not empty."),
- self.tr("Recursive deletion is not supported."),
- self.tr("Please delete the content first."),
+ self.makeAlert(self.tr(
+ "Cannot delete folder. It is not empty. "
+ "Recursive deletion is not supported. "
+ "Please delete the content first."
), nwAlert.ERROR)
return False
@@ -589,10 +588,10 @@ class GuiProjectTree(QTreeWidget):
self.theParent.mainMenu.setAvailableRoot()
self._setTreeChanged(True)
else:
- self.makeAlert((
- self.tr("Cannot delete root folder. It is not empty."),
- self.tr("Recursive deletion is not supported."),
- self.tr("Please delete the content first."),
+ self.makeAlert(self.tr(
+ "Cannot delete root folder. It is not empty. "
+ "Recursive deletion is not supported. "
+ "Please delete the content first."
), nwAlert.ERROR)
return False
@@ -974,9 +973,9 @@ class GuiProjectTree(QTreeWidget):
self.addTopLevelItem(newItem)
else:
self.makeAlert(
- self.tr("There is nowhere to add item with name '{0}'").format(
- nwItem.itemName),
- nwAlert.ERROR
+ self.tr(
+ "There is nowhere to add item with name '{0}'").format(nwItem.itemName
+ ), nwAlert.ERROR
)
del self._treeMap[tHandle]
return None
diff --git a/nw/gui/projwizard.py b/nw/gui/projwizard.py
index fc854f16..e3efc484 100644
--- a/nw/gui/projwizard.py
+++ b/nw/gui/projwizard.py
@@ -28,7 +28,7 @@ import nw
import logging
import os
-from PyQt5.QtCore import QCoreApplication, Qt
+from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QWizard, QWizardPage, QLabel, QVBoxLayout, QLineEdit, QPlainTextEdit,
QPushButton, QFileDialog, QHBoxLayout, QRadioButton, QFormLayout,
@@ -36,7 +36,7 @@ from PyQt5.QtWidgets import (
)
from nw.common import makeFileNameSafe
-from nw.constants import nwLabels, nwItemClass
+from nw.constants import trConst, nwLabels, nwItemClass
from nw.gui.custom import QSwitch
logger = logging.getLogger(__name__)
@@ -96,10 +96,12 @@ class ProjWizardIntroPage(QWizardPage):
self.setTitle(self.tr("Create New Project"))
self.theText = QLabel(
- self.tr("Provide at least a working title. The working title should not "
- "be change beyond this point as it is used by the application for "
- "generating file names for for instance backups. The other fields "
- "are optional and can be changed at any time in Project Settings.")
+ self.tr(
+ "Provide at least a working title. The working title should not "
+ "be change beyond this point as it is used by the application for "
+ "generating file names for for instance backups. The other fields "
+ "are optional and can be changed at any time in Project Settings."
+ )
)
self.theText.setWordWrap(True)
@@ -166,8 +168,10 @@ class ProjWizardFolderPage(QWizardPage):
self.setTitle(self.tr("Select Project Folder"))
self.theText = QLabel(
- self.tr("Select a location to store the project. A new project folder "
- "will be created in the selected location.")
+ self.tr(
+ "Select a location to store the project. A new project folder "
+ "will be created in the selected location."
+ )
)
self.theText.setWordWrap(True)
@@ -240,9 +244,11 @@ class ProjWizardPopulatePage(QWizardPage):
self.setTitle(self.tr("Populate Project"))
self.theText = QLabel(
- self.tr("Choose how to pre-fill the project. Either with a minimal set of "
- "starter items, an example project explaining and showing many of "
- "the features, or show further custom options on the next page.")
+ self.tr(
+ "Choose how to pre-fill the project. Either with a minimal set of "
+ "starter items, an example project explaining and showing many of "
+ "the features, or show further custom options on the next page."
+ )
)
self.theText.setWordWrap(True)
@@ -295,9 +301,11 @@ class ProjWizardCustomPage(QWizardPage):
self.setTitle(self.tr("Custom Project Options"))
self.theText = QLabel(
- self.tr("Select which additional root folders to make, and how to populate "
- "the Novel folder. If you don't want to add chapters or scenes, set "
- "the values to 0. You can add scenes without chapters.")
+ self.tr(
+ "Select which additional root folders to make, and how to populate "
+ "the Novel folder. If you don't want to add chapters or scenes, set "
+ "the values to 0. You can add scenes without chapters."
+ )
)
self.theText.setWordWrap(True)
@@ -308,18 +316,24 @@ class ProjWizardCustomPage(QWizardPage):
self.rootForm = QGridLayout()
self.rootGroup.setLayout(self.rootForm)
- self.lblPlot = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.PLOT])))
- self.lblChar = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.CHARACTER])))
- self.lblWorld = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.WORLD])))
- self.lblTime = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.TIMELINE])))
+ self.lblPlot = QLabel(self.tr("{0} folder").format(
+ trConst(nwLabels.CLASS_NAME[nwItemClass.PLOT]))
+ )
+ self.lblChar = QLabel(self.tr("{0} folder").format(
+ trConst(nwLabels.CLASS_NAME[nwItemClass.CHARACTER]))
+ )
+ self.lblWorld = QLabel(self.tr("{0} folder").format(
+ trConst(nwLabels.CLASS_NAME[nwItemClass.WORLD]))
+ )
+ self.lblTime = QLabel(self.tr("{0} folder").format(
+ trConst(nwLabels.CLASS_NAME[nwItemClass.TIMELINE]))
+ )
self.lblObject = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.OBJECT])))
+ trConst(nwLabels.CLASS_NAME[nwItemClass.OBJECT]))
+ )
self.lblEntity = QLabel(self.tr("{0} folder").format(
- QCoreApplication.translate("Constant", nwLabels.CLASS_NAME[nwItemClass.ENTITY])))
+ trConst(nwLabels.CLASS_NAME[nwItemClass.ENTITY]))
+ )
self.addPlot = QSwitch()
self.addChar = QSwitch()
@@ -407,9 +421,10 @@ class ProjWizardFinalPage(QWizardPage):
self.setTitle(self.tr("Finished"))
self.theText = QLabel("".join([
- ("%s
" % self.tr("All done.")),
- ("%s
" % self.tr("Press '{0}' to create the new project.").format(
- self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish")))
+ "%s
" % self.tr("All done."),
+ "%s
" % self.tr("Press '{0}' to create the new project.").format(
+ self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish")
+ )
]))
self.theText.setWordWrap(True)
diff --git a/nw/gui/theme.py b/nw/gui/theme.py
index fc30a839..946a6435 100644
--- a/nw/gui/theme.py
+++ b/nw/gui/theme.py
@@ -31,8 +31,9 @@ import configparser
import os
from math import ceil
+from functools import partial
-from PyQt5.QtCore import Qt
+from PyQt5.QtCore import QCoreApplication, Qt
from PyQt5.QtWidgets import QStyle, qApp
from PyQt5.QtGui import (
QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap
@@ -157,6 +158,10 @@ class GuiTheme:
logger.verbose("Text 'N' Height: %d" % self.textNHeight)
logger.verbose("Text 'N' Width: %d" % self.textNWidth)
+ # Internal Mapping
+ self.makeAlert = self.theParent.makeAlert
+ self.tr = partial(QCoreApplication.translate, "GuiTheme")
+
return
##
@@ -392,7 +397,7 @@ class GuiTheme:
with open(themeConf, mode="r", encoding="utf8") as inFile:
confParser.read_file(inFile)
except Exception as e:
- self.theParent.makeAlert(
+ self.makeAlert(
[self.tr("Could not load theme config file."), str(e)], nwAlert.ERROR
)
continue
@@ -425,7 +430,7 @@ class GuiTheme:
with open(syntaxPath, mode="r", encoding="utf8") as inFile:
confParser.read_file(inFile)
except Exception as e:
- self.theParent.makeAlert(
+ self.makeAlert(
[self.tr("Could not load syntax file."), str(e)], nwAlert.ERROR
)
return []
@@ -740,7 +745,7 @@ class GuiIcons:
with open(themeConf, mode="r", encoding="utf8") as inFile:
confParser.read_file(inFile)
except Exception as e:
- self.theParent.makeAlert(
+ self.makeAlert(
[self.tr("Could not load theme config file."), str(e)], nwAlert.ERROR
)
continue
diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py
index 44fd38e5..2a48213a 100644
--- a/nw/gui/writingstats.py
+++ b/nw/gui/writingstats.py
@@ -159,18 +159,27 @@ class GuiWritingStats(QDialog):
self.totalWords.setFont(self.theTheme.guiFontFixed)
self.totalWords.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Total Time"))), 0, 0)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Idle Time"))), 1, 0)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Filtered Time"))), 2, 0)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Novel Word Count"))), 3, 0)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Notes Word Count"))), 4, 0)
- self.infoForm.addWidget(QLabel(self.tr("{0}:").format(self.tr("Total Word Count"))), 5, 0)
+ lblTTime = QLabel(self.tr("{0}:").format(self.tr("Total Time")))
+ lblITime = QLabel(self.tr("{0}:").format(self.tr("Idle Time")))
+ lblFTime = QLabel(self.tr("{0}:").format(self.tr("Filtered Time")))
+ lblNvCount = QLabel(self.tr("{0}:").format(self.tr("Novel Word Count")))
+ lblNtCount = QLabel(self.tr("{0}:").format(self.tr("Notes Word Count")))
+ lblTtCount = QLabel(self.tr("{0}:").format(self.tr("Total Word Count")))
+
+ self.infoForm.addWidget(lblTTime, 0, 0)
+ self.infoForm.addWidget(lblITime, 1, 0)
+ self.infoForm.addWidget(lblFTime, 2, 0)
+ self.infoForm.addWidget(lblNvCount, 3, 0)
+ self.infoForm.addWidget(lblNtCount, 4, 0)
+ self.infoForm.addWidget(lblTtCount, 5, 0)
+
self.infoForm.addWidget(self.labelTotal, 0, 1)
self.infoForm.addWidget(self.labelIdleT, 1, 1)
self.infoForm.addWidget(self.labelFilter, 2, 1)
self.infoForm.addWidget(self.novelWords, 3, 1)
self.infoForm.addWidget(self.notesWords, 4, 1)
self.infoForm.addWidget(self.totalWords, 5, 1)
+
self.infoForm.setRowStretch(6, 1)
# Filter Options
diff --git a/nw/guimain.py b/nw/guimain.py
index 2af04c74..618a95e5 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -358,9 +358,10 @@ class GuiMain(QMainWindow):
if os.path.isfile(os.path.join(projPath, self.theProject.projFile)):
self.makeAlert(
- self.tr("A project already exists in that location. "
- "Please choose another folder."),
- nwAlert.ERROR
+ self.tr(
+ "A project already exists in that location. "
+ "Please choose another folder."
+ ), nwAlert.ERROR
)
return False
@@ -394,8 +395,10 @@ class GuiMain(QMainWindow):
if not isYes:
msgYes = self.askQuestion(
self.tr("Close Project"),
- "%s
%s" % (self.tr("Close the current project?"),
- self.tr("Changes are saved automatically."))
+ "%s
%s" % (
+ self.tr("Close the current project?"),
+ self.tr("Changes are saved automatically.")
+ )
)
if not msgYes:
return False
@@ -461,9 +464,11 @@ class GuiMain(QMainWindow):
try:
lockDetails = (
- "
%s" % self.tr("The project was locked by the computer "
- "'{computer_name}' ({os_name} {os_version}), "
- "last active on {time}")
+ "
%s" % self.tr(
+ "The project was locked by the computer "
+ "'{computer_name}' ({os_name} {os_version}), "
+ "last active on {time}"
+ )
).format(
computer_name = self.theProject.lockedBy[0],
os_name = self.theProject.lockedBy[1],
@@ -479,12 +484,16 @@ class GuiMain(QMainWindow):
msgRes = msgBox.warning(
self, self.tr("Project Locked"),
"%s
%s
%s" % (
- self.tr("The project is already open by another instance of novelWriter, and "
- "is therefore locked. Override lock and continue anyway?"),
- self.tr("Note: If the program or the computer previously crashed, the lock "
- "can safely be overridden. If, however, another instance of "
- "novelWriter has the project open, overriding the lock may corrupt "
- "the project, and is not recommended."),
+ self.tr(
+ "The project is already open by another instance of novelWriter, and "
+ "is therefore locked. Override lock and continue anyway?"
+ ),
+ self.tr(
+ "Note: If the program or the computer previously crashed, the lock "
+ "can safely be overridden. If, however, another instance of "
+ "novelWriter has the project open, overriding the lock may corrupt "
+ "the project, and is not recommended."
+ ),
lockDetails
),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
@@ -732,10 +741,13 @@ class GuiMain(QMainWindow):
return False
if not self.docEditor.isEmpty():
- msgYes = self.askQuestion(self.tr("Import Document"), (
- self.tr("Importing the file will overwrite the current content of the document. "
- "Do you want to proceed?")
- ))
+ msgYes = self.askQuestion(
+ self.tr("Import Document"),
+ self.tr(
+ "Importing the file will overwrite the current content of the document. "
+ "Do you want to proceed?"
+ )
+ )
if not msgYes:
return False
@@ -874,9 +886,12 @@ class GuiMain(QMainWindow):
if tItem is not None:
self.setStatus(self.tr("{0}: '{1}'").format(self.tr("Indexing"), tItem.itemName))
else:
- self.setStatus(self.tr("{0}: {1}").format(
- self.tr("Indexing"),
- self.tr("Unknown item")))
+ self.setStatus(
+ self.tr("{0}: {1}").format(
+ self.tr("Indexing"),
+ self.tr("Unknown item")
+ )
+ )
if tItem is not None and tItem.itemType == nwItemType.FILE:
logger.verbose("Scanning: %s" % tItem.itemName)
@@ -894,14 +909,16 @@ class GuiMain(QMainWindow):
self.treeView.projectWordCount()
tEnd = time()
- self.setStatus(self.tr("Indexing completed in {0} ms").
- format(f"{(tEnd - tStart)*1000.0:.1f}"))
+ self.setStatus(
+ self.tr("Indexing completed in {0} ms").format(f"{(tEnd - tStart)*1000.0:.1f}")
+ )
self.docEditor.updateTagHighLighting()
qApp.restoreOverrideCursor()
if not beQuiet:
- self.makeAlert(self.tr("The project index has been successfully rebuilt."),
- nwAlert.INFO)
+ self.makeAlert(
+ self.tr("The project index has been successfully rebuilt."), nwAlert.INFO
+ )
return True
@@ -1153,8 +1170,10 @@ class GuiMain(QMainWindow):
if self.hasProject:
msgYes = self.askQuestion(
self.tr("Exit"),
- "%s
%s" % (self.tr("Do you want to exit novelWriter?"),
- self.tr("Changes are saved automatically."))
+ "%s
%s" % (
+ self.tr("Do you want to exit novelWriter?"),
+ self.tr("Changes are saved automatically.")
+ )
)
if not msgYes:
return False
diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx
index 3e1756e3..94a7dcc9 100644
--- a/sample/nwProject.nwx
+++ b/sample/nwProject.nwx
@@ -1,13 +1,13 @@
-
+
Sample Project
Sample Project
Jane Smith
Jay Doh
- 936
+ 1019
161
- 46791
+ 48272
False
@@ -120,7 +120,7 @@
1810
318
8
- 3
+ 1112
-
Another Scene