Merge pull request #673 from bkmeneguello/i18n
Project basic internationalization support
This commit is contained in:
Binary file not shown.
+4709
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,447 @@
|
||||
<!DOCTYPE QPH>
|
||||
<QPH sourcelanguage="en" language="pt">
|
||||
<phrase>
|
||||
<source>Point of View</source>
|
||||
<target>Ponto de Vista</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Characters</source>
|
||||
<target>Personagens</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Plot</source>
|
||||
<target>Enredo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Timeline</source>
|
||||
<target>Linha do Tempo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Locations</source>
|
||||
<target>Lugares</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Objects</source>
|
||||
<target>Objetos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Entities</source>
|
||||
<target>Entidades</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>None</source>
|
||||
<target>Nenhum</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Novel</source>
|
||||
<target>Livro</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Entity</source>
|
||||
<target>Entidade</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Outtakes</source>
|
||||
<target>Removidos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Trash</source>
|
||||
<target>Lixeira</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Title Page</source>
|
||||
<target>Página de Título</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Book</source>
|
||||
<target>Livro</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Plain Page</source>
|
||||
<target>Página</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Partition</source>
|
||||
<target>Partição</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Unnumbered</source>
|
||||
<target>Sem Numeração</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Scene</source>
|
||||
<target>Cena</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Note</source>
|
||||
<target>Nota</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Title</source>
|
||||
<target>Título</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Level</source>
|
||||
<target>Nível</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Document</source>
|
||||
<target>Documento</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Line</source>
|
||||
<target>Linha</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Chars</source>
|
||||
<target>Caracteres</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Words</source>
|
||||
<target>Palavras</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Synopsis</source>
|
||||
<target>Sinopse</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>About</source>
|
||||
<target>Sobre</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Release</source>
|
||||
<target>Versões</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>About novelWriter</source>
|
||||
<target>Sobre o novelWriter</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Credits</source>
|
||||
<target>Créditos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Author</source>
|
||||
<target>Autor</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Credit</source>
|
||||
<target>Créditos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>License</source>
|
||||
<target>Licença</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Theme</source>
|
||||
<target>Tema</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Icons</source>
|
||||
<target>Ícones</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Syntax</source>
|
||||
<target>Sintaxe</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Website</source>
|
||||
<target>Website</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Chapter</source>
|
||||
<target>Capítulo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Section</source>
|
||||
<target>Seção</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Font family</source>
|
||||
<target>Família da fonte</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Font size</source>
|
||||
<target>Tamanho da fonte</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Justify text</source>
|
||||
<target>Texto justificado</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Print</source>
|
||||
<target>Imprimir</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Build Project</source>
|
||||
<target>Construir o Projeto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Save As</source>
|
||||
<target>Salvar Como</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Close</source>
|
||||
<target>Fechar</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Plain Text</source>
|
||||
<target>Texto Simples</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Plain HTML</source>
|
||||
<target>HTML Simples</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Save Document As</source>
|
||||
<target>Salvar Documento Como</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Unknown</source>
|
||||
<target>Desconhecido</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Look and Feel</source>
|
||||
<target>Aparência</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Project Backup</source>
|
||||
<target>Cópia de Segurança</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Path</source>
|
||||
<target>Caminho</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Status</source>
|
||||
<target>Estado</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Replace</source>
|
||||
<target>Substituir</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Search</source>
|
||||
<target>Pesquisa</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Handle</source>
|
||||
<target>Referência</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>References</source>
|
||||
<target>Referências</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Label</source>
|
||||
<target>Rótulo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Class</source>
|
||||
<target>Classe</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Layout</source>
|
||||
<target>Leiaute</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source> Characters</source>
|
||||
<target>Caracteres</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Editor</source>
|
||||
<target>Editor</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Project</source>
|
||||
<target>Projeto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Provider</source>
|
||||
<target>Provedor</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>unknown</source>
|
||||
<target>desconhecido</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Paragraphs</source>
|
||||
<target>Parágrafos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Default</source>
|
||||
<target>Padrão</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Working title</source>
|
||||
<target>Nome do projeto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Project path</source>
|
||||
<target>Caminho do projeto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Project Stats</source>
|
||||
<target>Estatíticas do Projeto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Folders</source>
|
||||
<target>Diretórios</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Documents</source>
|
||||
<target>Documentos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Word count</source>
|
||||
<target>Contagem de palavras</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Keyword</source>
|
||||
<target>Palavra-chave</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>New</source>
|
||||
<target>Novo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Delete</source>
|
||||
<target>Remover</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Save</source>
|
||||
<target>Salvar</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Name</source>
|
||||
<target>Nome</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>New Item</source>
|
||||
<target>Novo Item</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Last Opened</source>
|
||||
<target>Aberto Pela Última Vez</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Settings</source>
|
||||
<target>Configurações</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Details</source>
|
||||
<target>Detalhes</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Importance</source>
|
||||
<target>Importância</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Auto-Replace</source>
|
||||
<target>Substituir automaticamente</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Flag</source>
|
||||
<target>Opção</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Flags</source>
|
||||
<target>Opções</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>(New Entry)</source>
|
||||
<target></target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>New File</source>
|
||||
<target>Novo Arquivo</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>New Folder</source>
|
||||
<target>Novo Diretório</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Histogram</source>
|
||||
<target>Histograma</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Finished</source>
|
||||
<target>Finalizado</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Done</source>
|
||||
<target>Pronto</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Finish</source>
|
||||
<target>Terminar</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Auto-Replace</source>
|
||||
<target>Substituição Automática</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>No Suggestions</source>
|
||||
<target>Sem Sugestões</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Browse</source>
|
||||
<target>Procurar</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Tag</source>
|
||||
<target>Etiqueta</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Draft</source>
|
||||
<target>Rascunho</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Minor</source>
|
||||
<target>Menor</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Major</source>
|
||||
<target>Maior</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Backup</source>
|
||||
<target>Cópia de Segurança</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Undo</source>
|
||||
<target>Desfazer</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Release</source>
|
||||
<target>Lançamento</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Pages</source>
|
||||
<target>Páginas</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Page</source>
|
||||
<target>Página</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Progress</source>
|
||||
<target>Progresso</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Chapters</source>
|
||||
<target>Capítulos</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Scenes</source>
|
||||
<target>Cenas</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>Revisions</source>
|
||||
<target>Revisões</target>
|
||||
</phrase>
|
||||
<phrase>
|
||||
<source>seconds</source>
|
||||
<target>segundos</target>
|
||||
</phrase>
|
||||
</QPH>
|
||||
@@ -0,0 +1,33 @@
|
||||
SOURCES += \
|
||||
nw/constants/constants.py \
|
||||
nw/core/document.py \
|
||||
nw/core/project.py \
|
||||
nw/core/tokenizer.py \
|
||||
nw/gui/about.py \
|
||||
nw/gui/build.py \
|
||||
nw/gui/custom.py \
|
||||
nw/gui/doceditor.py \
|
||||
nw/gui/docmerge.py \
|
||||
nw/gui/docsplit.py \
|
||||
nw/gui/docviewer.py \
|
||||
nw/gui/itemdetails.py \
|
||||
nw/gui/itemeditor.py \
|
||||
nw/gui/mainmenu.py \
|
||||
nw/gui/noveltree.py \
|
||||
nw/gui/outline.py \
|
||||
nw/gui/outlinedetails.py \
|
||||
nw/gui/preferences.py \
|
||||
nw/gui/projdetails.py \
|
||||
nw/gui/projload.py \
|
||||
nw/gui/projsettings.py \
|
||||
nw/gui/projtree.py \
|
||||
nw/gui/projwizard.py \
|
||||
nw/gui/statusbar.py \
|
||||
nw/gui/theme.py \
|
||||
nw/gui/wordlist.py \
|
||||
nw/gui/writingstats.py \
|
||||
nw/error.py \
|
||||
nw/guimain.py
|
||||
|
||||
TRANSLATIONS += \
|
||||
i18n/nw_pt.ts
|
||||
@@ -285,6 +285,7 @@ def main(sysArgs=None):
|
||||
sys.excepthook = exceptionHandler
|
||||
|
||||
# Launch main GUI
|
||||
CONFIG.initLocalisation(nwApp)
|
||||
nwGUI = GuiMain()
|
||||
if not nwGUI.hasProject:
|
||||
nwGUI.showProjectLoadDialog()
|
||||
|
||||
+44
-3
@@ -34,7 +34,10 @@ import os
|
||||
from time import time
|
||||
|
||||
from PyQt5.Qt import PYQT_VERSION_STR
|
||||
from PyQt5.QtCore import QT_VERSION_STR, QStandardPaths, QSysInfo
|
||||
from PyQt5.QtCore import (
|
||||
QT_VERSION_STR, QStandardPaths, QSysInfo, QLocale, QLibraryInfo,
|
||||
QTranslator
|
||||
)
|
||||
|
||||
from nw.constants import nwConst, nwFiles, nwUnicode
|
||||
from nw.common import splitVersionNumber, formatTimeStamp
|
||||
@@ -84,12 +87,18 @@ class Config:
|
||||
self.guiSyntax = "default_light"
|
||||
self.guiIcons = "typicons_colour_light"
|
||||
self.guiDark = False # Load icons for dark backgrounds, if available
|
||||
self.guiLang = "en" # Hardcoded for now since the GUI is only in English
|
||||
self.guiFont = "" # Defaults to system default font
|
||||
self.guiFontSize = 11
|
||||
self.guiFontSize = 11 # Is overridden if system default is loaded
|
||||
self.guiScale = 1.0 # Set automatically by Theme class
|
||||
self.lastNotes = "0x0" # The latest release notes that have been shown
|
||||
|
||||
## Localisation
|
||||
self.qLocal = QLocale.system()
|
||||
self.guiLang = self.qLocal.name()
|
||||
self.qtLangPath = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
|
||||
self.nwLangPath = None
|
||||
self.qtTrans = {}
|
||||
|
||||
## Sizes
|
||||
self.winGeometry = [1200, 650]
|
||||
self.treeColWidth = [200, 50, 30]
|
||||
@@ -290,6 +299,9 @@ class Config:
|
||||
self.iconPath = os.path.join(self.assetPath, "icons")
|
||||
self.appIcon = os.path.join(self.iconPath, "novelwriter.svg")
|
||||
|
||||
# Internationalisation
|
||||
self.nwLangPath = os.path.join(self.appRoot, "i18n")
|
||||
|
||||
logger.verbose("App path: %s" % self.appPath)
|
||||
logger.verbose("Last path: %s" % self.lastPath)
|
||||
|
||||
@@ -354,6 +366,31 @@ class Config:
|
||||
|
||||
return True
|
||||
|
||||
def initLocalisation(self, nwApp):
|
||||
"""Initialise the localisation of the GUI.
|
||||
"""
|
||||
self.qLocal = QLocale(self.guiLang)
|
||||
QLocale.setDefault(self.qLocal)
|
||||
self.qtTrans = {}
|
||||
|
||||
langList = [
|
||||
(self.qtLangPath, "qt"), # Qt 4.x
|
||||
(self.qtLangPath, "qtbase"), # Qt 5.x
|
||||
(self.nwLangPath, "qtbase"), # Alternative Qt 5.x
|
||||
(self.nwLangPath, "nw"), # novelWriter
|
||||
]
|
||||
for lngPath, lngBase in langList:
|
||||
for lngCode in self.qLocal.uiLanguages():
|
||||
qTrans = QTranslator()
|
||||
lngFile = "%s_%s" % (lngBase, lngCode)
|
||||
if lngFile not in self.qtTrans:
|
||||
if qTrans.load(lngFile, lngPath):
|
||||
logger.debug("Loaded: %s" % qTrans.filePath())
|
||||
nwApp.installTranslator(qTrans)
|
||||
self.qtTrans[lngFile] = qTrans
|
||||
|
||||
return
|
||||
|
||||
def loadConfig(self):
|
||||
"""Load preferences from file and replace default settings.
|
||||
"""
|
||||
@@ -397,6 +434,9 @@ class Config:
|
||||
self.lastNotes = self._parseLine(
|
||||
cnfParse, cnfSec, "lastnotes", self.CNF_STR, self.lastNotes
|
||||
)
|
||||
self.guiLang = self._parseLine(
|
||||
cnfParse, cnfSec, "guilang", self.CNF_STR, self.guiLang
|
||||
)
|
||||
|
||||
## Sizes
|
||||
cnfSec = "Sizes"
|
||||
@@ -626,6 +666,7 @@ class Config:
|
||||
cnfParse.set(cnfSec, "guifont", str(self.guiFont))
|
||||
cnfParse.set(cnfSec, "guifontsize", str(self.guiFontSize))
|
||||
cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes))
|
||||
cnfParse.set(cnfSec, "guilang", str(self.guiLang))
|
||||
|
||||
## Sizes
|
||||
cnfSec = "Sizes"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from nw.constants.iso import isoLanguage, isoCountry
|
||||
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,
|
||||
@@ -10,8 +9,7 @@ from nw.constants.enum import (
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"isoCountry",
|
||||
"isoLanguage",
|
||||
"trConst",
|
||||
"nwConst",
|
||||
"nwLists",
|
||||
"nwRegEx",
|
||||
|
||||
+66
-59
@@ -24,10 +24,17 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
|
||||
|
||||
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
|
||||
@@ -119,17 +126,17 @@ class nwKeyWords:
|
||||
class nwLabels():
|
||||
|
||||
CLASS_NAME = {
|
||||
nwItemClass.NO_CLASS : "None",
|
||||
nwItemClass.NOVEL : "Novel",
|
||||
nwItemClass.PLOT : "Plot",
|
||||
nwItemClass.CHARACTER : "Characters",
|
||||
nwItemClass.WORLD : "Locations",
|
||||
nwItemClass.TIMELINE : "Timeline",
|
||||
nwItemClass.OBJECT : "Objects",
|
||||
nwItemClass.ENTITY : "Entity",
|
||||
nwItemClass.CUSTOM : "Custom",
|
||||
nwItemClass.ARCHIVE : "Outtakes",
|
||||
nwItemClass.TRASH : "Trash",
|
||||
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"),
|
||||
}
|
||||
CLASS_FLAG = {
|
||||
nwItemClass.NO_CLASS : "0",
|
||||
@@ -158,15 +165,15 @@ class nwLabels():
|
||||
nwItemClass.TRASH : "cls_trash",
|
||||
}
|
||||
LAYOUT_NAME = {
|
||||
nwItemLayout.NO_LAYOUT : "None",
|
||||
nwItemLayout.TITLE : "Title Page",
|
||||
nwItemLayout.BOOK : "Book",
|
||||
nwItemLayout.PAGE : "Plain Page",
|
||||
nwItemLayout.PARTITION : "Partition",
|
||||
nwItemLayout.UNNUMBERED : "Unnumbered",
|
||||
nwItemLayout.CHAPTER : "Chapter",
|
||||
nwItemLayout.SCENE : "Scene",
|
||||
nwItemLayout.NOTE : "Note",
|
||||
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"),
|
||||
}
|
||||
LAYOUT_FLAG = {
|
||||
nwItemLayout.NO_LAYOUT : "Xo",
|
||||
@@ -180,27 +187,27 @@ class nwLabels():
|
||||
nwItemLayout.NOTE : "Nt",
|
||||
}
|
||||
KEY_NAME = {
|
||||
nwKeyWords.TAG_KEY : "Tag",
|
||||
nwKeyWords.POV_KEY : "Point of View",
|
||||
nwKeyWords.FOCUS_KEY : "Focus",
|
||||
nwKeyWords.CHAR_KEY : "Characters",
|
||||
nwKeyWords.PLOT_KEY : "Plot",
|
||||
nwKeyWords.TIME_KEY : "Timeline",
|
||||
nwKeyWords.WORLD_KEY : "Locations",
|
||||
nwKeyWords.OBJECT_KEY : "Objects",
|
||||
nwKeyWords.ENTITY_KEY : "Entities",
|
||||
nwKeyWords.CUSTOM_KEY : "Custom",
|
||||
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"),
|
||||
}
|
||||
OUTLINE_COLS = {
|
||||
nwOutline.TITLE : "Title",
|
||||
nwOutline.LEVEL : "Level",
|
||||
nwOutline.LABEL : "Document",
|
||||
nwOutline.LINE : "Line",
|
||||
nwOutline.CCOUNT : "Chars",
|
||||
nwOutline.WCOUNT : "Words",
|
||||
nwOutline.PCOUNT : "Pars",
|
||||
nwOutline.POV : "POV",
|
||||
nwOutline.FOCUS : "Focus",
|
||||
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.CHAR : KEY_NAME[nwKeyWords.CHAR_KEY],
|
||||
nwOutline.PLOT : KEY_NAME[nwKeyWords.PLOT_KEY],
|
||||
nwOutline.TIME : KEY_NAME[nwKeyWords.TIME_KEY],
|
||||
@@ -208,7 +215,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 : "Synopsis",
|
||||
nwOutline.SYNOP : QT_TRANSLATE_NOOP("Constant", "Synopsis"),
|
||||
}
|
||||
|
||||
# END Class nwLabels
|
||||
@@ -218,28 +225,28 @@ class nwQuotes():
|
||||
Source: https://en.wikipedia.org/wiki/Quotation_mark
|
||||
"""
|
||||
SYMBOLS = {
|
||||
"\u0027" : "Straight single quotation mark",
|
||||
"\u0022" : "Straight double quotation mark",
|
||||
"\u0027" : QT_TRANSLATE_NOOP("Constant", "Straight single quotation mark"),
|
||||
"\u0022" : QT_TRANSLATE_NOOP("Constant", "Straight double quotation mark"),
|
||||
|
||||
"\u2018" : "Left single quotation mark",
|
||||
"\u2019" : "Right single quotation mark",
|
||||
"\u201a" : "Single low-9 quotation mark",
|
||||
"\u201b" : "Single high-reversed-9 quotation mark",
|
||||
"\u201c" : "Left double quotation mark",
|
||||
"\u201d" : "Right double quotation mark",
|
||||
"\u201e" : "Double low-9 quotation mark",
|
||||
"\u201f" : "Double high-reversed-9 quotation mark",
|
||||
"\u2e42" : "Double low-reversed-9 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"),
|
||||
|
||||
"\u2039" : "Single left-pointing angle quotation mark",
|
||||
"\u203a" : "Single right-pointing angle quotation mark",
|
||||
"\u00ab" : "Left-pointing double angle quotation mark",
|
||||
"\u00bb" : "Right-pointing double angle 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"),
|
||||
|
||||
"\u300c" : "Left corner bracket",
|
||||
"\u300d" : "Right corner bracket",
|
||||
"\u300e" : "Left white corner bracket",
|
||||
"\u300f" : "Right white corner bracket",
|
||||
"\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"),
|
||||
}
|
||||
|
||||
# END Class nwQuotes
|
||||
|
||||
@@ -1,472 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
novelWriter – ISO Codes
|
||||
=======================
|
||||
Handles translating language codes to language names
|
||||
|
||||
File History:
|
||||
Created: 2019-11-05 [0.4.0]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2021, Veronica Berglyd Olsen
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
class isoLanguage():
|
||||
|
||||
ISO_639_1 = {
|
||||
"aa" : "Afar",
|
||||
"ab" : "Abkhazian",
|
||||
"ae" : "Avestan",
|
||||
"af" : "Afrikaans",
|
||||
"ak" : "Akan",
|
||||
"am" : "Amharic",
|
||||
"an" : "Aragonese",
|
||||
"ar" : "Arabic",
|
||||
"as" : "Assamese",
|
||||
"av" : "Avaric",
|
||||
"ay" : "Aymara",
|
||||
"az" : "Azerbaijani",
|
||||
"ba" : "Bashkir",
|
||||
"be" : "Belarusian",
|
||||
"bg" : "Bulgarian",
|
||||
"bh" : "Bihari languages",
|
||||
"bi" : "Bislama",
|
||||
"bm" : "Bambara",
|
||||
"bn" : "Bengali",
|
||||
"bo" : "Tibetan",
|
||||
"br" : "Breton",
|
||||
"bs" : "Bosnian",
|
||||
"ca" : "Catalan",
|
||||
"ce" : "Chechen",
|
||||
"ch" : "Chamorro",
|
||||
"co" : "Corsican",
|
||||
"cr" : "Cree",
|
||||
"cs" : "Czech",
|
||||
"cu" : "Church Slavic",
|
||||
"cv" : "Chuvash",
|
||||
"cy" : "Welsh",
|
||||
"da" : "Danish",
|
||||
"de" : "German",
|
||||
"dv" : "Divehi",
|
||||
"dz" : "Dzongkha",
|
||||
"ee" : "Ewe",
|
||||
"el" : "Modern Greek",
|
||||
"en" : "English",
|
||||
"eo" : "Esperanto",
|
||||
"es" : "Spanish",
|
||||
"et" : "Estonian",
|
||||
"eu" : "Basque",
|
||||
"fa" : "Persian",
|
||||
"ff" : "Fulah",
|
||||
"fi" : "Finnish",
|
||||
"fj" : "Fijian",
|
||||
"fo" : "Faroese",
|
||||
"fr" : "French",
|
||||
"fy" : "Western Frisian",
|
||||
"ga" : "Irish",
|
||||
"gd" : "Gaelic",
|
||||
"gl" : "Galician",
|
||||
"gn" : "Guarani",
|
||||
"gu" : "Gujarati",
|
||||
"gv" : "Manx",
|
||||
"ha" : "Hausa",
|
||||
"he" : "Hebrew",
|
||||
"hi" : "Hindi",
|
||||
"ho" : "Hiri Motu",
|
||||
"hr" : "Croatian",
|
||||
"ht" : "Haitian",
|
||||
"hu" : "Hungarian",
|
||||
"hy" : "Armenian",
|
||||
"hz" : "Herero",
|
||||
"ia" : "Interlingua",
|
||||
"id" : "Indonesian",
|
||||
"ie" : "Interlingue",
|
||||
"ig" : "Igbo",
|
||||
"ii" : "Sichuan Yi",
|
||||
"ik" : "Inupiaq",
|
||||
"io" : "Ido",
|
||||
"is" : "Icelandic",
|
||||
"it" : "Italian",
|
||||
"iu" : "Inuktitut",
|
||||
"ja" : "Japanese",
|
||||
"jv" : "Javanese",
|
||||
"ka" : "Georgian",
|
||||
"kg" : "Kongo",
|
||||
"ki" : "Kikuyu",
|
||||
"kj" : "Kuanyama",
|
||||
"kk" : "Kazakh",
|
||||
"kl" : "Kalaallisut",
|
||||
"km" : "Central Khmer",
|
||||
"kn" : "Kannada",
|
||||
"ko" : "Korean",
|
||||
"kr" : "Kanuri",
|
||||
"ks" : "Kashmiri",
|
||||
"ku" : "Kurdish",
|
||||
"kv" : "Komi",
|
||||
"kw" : "Cornish",
|
||||
"ky" : "Kirghiz",
|
||||
"la" : "Latin",
|
||||
"lb" : "Luxembourgish",
|
||||
"lg" : "Ganda",
|
||||
"li" : "Limburgan",
|
||||
"ln" : "Lingala",
|
||||
"lo" : "Lao",
|
||||
"lt" : "Lithuanian",
|
||||
"lu" : "Luba-Katanga",
|
||||
"lv" : "Latvian",
|
||||
"mg" : "Malagasy",
|
||||
"mh" : "Marshallese",
|
||||
"mi" : "Maori",
|
||||
"mk" : "Macedonian",
|
||||
"ml" : "Malayalam",
|
||||
"mn" : "Mongolian",
|
||||
"mr" : "Marathi",
|
||||
"ms" : "Malay",
|
||||
"mt" : "Maltese",
|
||||
"my" : "Burmese",
|
||||
"na" : "Nauru",
|
||||
"nb" : "Norwegian Bokmål",
|
||||
"nd" : "North Ndebele",
|
||||
"ne" : "Nepali",
|
||||
"ng" : "Ndonga",
|
||||
"nl" : "Dutch",
|
||||
"nn" : "Norwegian Nynorsk",
|
||||
"no" : "Norwegian",
|
||||
"nr" : "South Ndebele",
|
||||
"nv" : "Navajo",
|
||||
"ny" : "Chichewa",
|
||||
"oc" : "Occitan",
|
||||
"oj" : "Ojibwa",
|
||||
"om" : "Oromo",
|
||||
"or" : "Oriya",
|
||||
"os" : "Ossetian",
|
||||
"pa" : "Panjabi",
|
||||
"pi" : "Pali",
|
||||
"pl" : "Polish",
|
||||
"ps" : "Pushto",
|
||||
"pt" : "Portuguese",
|
||||
"qu" : "Quechua",
|
||||
"rm" : "Romansh",
|
||||
"rn" : "Rundi",
|
||||
"ro" : "Romanian",
|
||||
"ru" : "Russian",
|
||||
"rw" : "Kinyarwanda",
|
||||
"sa" : "Sanskrit",
|
||||
"sc" : "Sardinian",
|
||||
"sd" : "Sindhi",
|
||||
"se" : "Northern Sami",
|
||||
"sg" : "Sango",
|
||||
"si" : "Sinhala",
|
||||
"sk" : "Slovak",
|
||||
"sl" : "Slovenian",
|
||||
"sm" : "Samoan",
|
||||
"sn" : "Shona",
|
||||
"so" : "Somali",
|
||||
"sq" : "Albanian",
|
||||
"sr" : "Serbian",
|
||||
"ss" : "Swati",
|
||||
"st" : "Southern Sotho",
|
||||
"su" : "Sundanese",
|
||||
"sv" : "Swedish",
|
||||
"sw" : "Swahili",
|
||||
"ta" : "Tamil",
|
||||
"te" : "Telugu",
|
||||
"tg" : "Tajik",
|
||||
"th" : "Thai",
|
||||
"ti" : "Tigrinya",
|
||||
"tk" : "Turkmen",
|
||||
"tl" : "Tagalog",
|
||||
"tn" : "Tswana",
|
||||
"to" : "Tonga",
|
||||
"tr" : "Turkish",
|
||||
"ts" : "Tsonga",
|
||||
"tt" : "Tatar",
|
||||
"tw" : "Twi",
|
||||
"ty" : "Tahitian",
|
||||
"ug" : "Uighur",
|
||||
"uk" : "Ukrainian",
|
||||
"ur" : "Urdu",
|
||||
"uz" : "Uzbek",
|
||||
"ve" : "Venda",
|
||||
"vi" : "Vietnamese",
|
||||
"vo" : "Volapük",
|
||||
"wa" : "Walloon",
|
||||
"wo" : "Wolof",
|
||||
"xh" : "Xhosa",
|
||||
"yi" : "Yiddish",
|
||||
"yo" : "Yoruba",
|
||||
"za" : "Zhuang",
|
||||
"zh" : "Chinese",
|
||||
"zu" : "Zulu",
|
||||
}
|
||||
|
||||
# END Class isoLanguage
|
||||
|
||||
class isoCountry():
|
||||
|
||||
ISO_3166_1_alpha_2 = {
|
||||
"AD" : "Andorra",
|
||||
"AE" : "United Arab Emirates",
|
||||
"AF" : "Afghanistan",
|
||||
"AG" : "Antigua and Barbuda",
|
||||
"AI" : "Anguilla",
|
||||
"AL" : "Albania",
|
||||
"AM" : "Armenia",
|
||||
"AO" : "Angola",
|
||||
"AQ" : "Antarctica",
|
||||
"AR" : "Argentina",
|
||||
"AS" : "American Samoa",
|
||||
"AT" : "Austria",
|
||||
"AU" : "Australia",
|
||||
"AW" : "Aruba",
|
||||
"AX" : "Åland Islands",
|
||||
"AZ" : "Azerbaijan",
|
||||
"BA" : "Bosnia and Herzegovina",
|
||||
"BB" : "Barbados",
|
||||
"BD" : "Bangladesh",
|
||||
"BE" : "Belgium",
|
||||
"BF" : "Burkina Faso",
|
||||
"BG" : "Bulgaria",
|
||||
"BH" : "Bahrain",
|
||||
"BI" : "Burundi",
|
||||
"BJ" : "Benin",
|
||||
"BL" : "Saint Barthélemy",
|
||||
"BM" : "Bermuda",
|
||||
"BN" : "Brunei Darussalam",
|
||||
"BO" : "Plurinational State of Bolivia",
|
||||
"BQ" : "Sint Eustatius and Saba Bonaire",
|
||||
"BR" : "Brazil",
|
||||
"BS" : "Bahamas",
|
||||
"BT" : "Bhutan",
|
||||
"BV" : "Bouvet Island",
|
||||
"BW" : "Botswana",
|
||||
"BY" : "Belarus",
|
||||
"BZ" : "Belize",
|
||||
"CA" : "Canada",
|
||||
"CC" : "Cocos (Keeling) Islands",
|
||||
"CD" : "The Democratic Republic of the Congo",
|
||||
"CF" : "Central African Republic",
|
||||
"CG" : "Congo",
|
||||
"CH" : "Switzerland",
|
||||
"CI" : "Côte d'Ivoire",
|
||||
"CK" : "Cook Islands",
|
||||
"CL" : "Chile",
|
||||
"CM" : "Cameroon",
|
||||
"CN" : "China",
|
||||
"CO" : "Colombia",
|
||||
"CR" : "Costa Rica",
|
||||
"CU" : "Cuba",
|
||||
"CV" : "Cape Verde",
|
||||
"CW" : "Curaçao",
|
||||
"CX" : "Christmas Island",
|
||||
"CY" : "Cyprus",
|
||||
"CZ" : "Czech Republic",
|
||||
"DE" : "Germany",
|
||||
"DJ" : "Djibouti",
|
||||
"DK" : "Denmark",
|
||||
"DM" : "Dominica",
|
||||
"DO" : "Dominican Republic",
|
||||
"DZ" : "Algeria",
|
||||
"EC" : "Ecuador",
|
||||
"EE" : "Estonia",
|
||||
"EG" : "Egypt",
|
||||
"EH" : "Western Sahara",
|
||||
"ER" : "Eritrea",
|
||||
"ES" : "Spain",
|
||||
"ET" : "Ethiopia",
|
||||
"FI" : "Finland",
|
||||
"FJ" : "Fiji",
|
||||
"FK" : "Falkland Islands (Malvinas)",
|
||||
"FM" : "Federated States of Micronesia",
|
||||
"FO" : "Faroe Islands",
|
||||
"FR" : "France",
|
||||
"GA" : "Gabon",
|
||||
"GB" : "United Kingdom",
|
||||
"GD" : "Grenada",
|
||||
"GE" : "Georgia",
|
||||
"GF" : "French Guiana",
|
||||
"GG" : "Guernsey",
|
||||
"GH" : "Ghana",
|
||||
"GI" : "Gibraltar",
|
||||
"GL" : "Greenland",
|
||||
"GM" : "Gambia",
|
||||
"GN" : "Guinea",
|
||||
"GP" : "Guadeloupe",
|
||||
"GQ" : "Equatorial Guinea",
|
||||
"GR" : "Greece",
|
||||
"GS" : "South Georgia and the South Sandwich Islands",
|
||||
"GT" : "Guatemala",
|
||||
"GU" : "Guam",
|
||||
"GW" : "Guinea-Bissau",
|
||||
"GY" : "Guyana",
|
||||
"HK" : "Hong Kong",
|
||||
"HM" : "Heard Island and McDonald Islands",
|
||||
"HN" : "Honduras",
|
||||
"HR" : "Croatia",
|
||||
"HT" : "Haiti",
|
||||
"HU" : "Hungary",
|
||||
"ID" : "Indonesia",
|
||||
"IE" : "Ireland",
|
||||
"IL" : "Israel",
|
||||
"IM" : "Isle of Man",
|
||||
"IN" : "India",
|
||||
"IO" : "British Indian Ocean Territory",
|
||||
"IQ" : "Iraq",
|
||||
"IR" : "Islamic Republic of Iran",
|
||||
"IS" : "Iceland",
|
||||
"IT" : "Italy",
|
||||
"JE" : "Jersey",
|
||||
"JM" : "Jamaica",
|
||||
"JO" : "Jordan",
|
||||
"JP" : "Japan",
|
||||
"KE" : "Kenya",
|
||||
"KG" : "Kyrgyzstan",
|
||||
"KH" : "Cambodia",
|
||||
"KI" : "Kiribati",
|
||||
"KM" : "Comoros",
|
||||
"KN" : "Saint Kitts and Nevis",
|
||||
"KP" : "Democratic People's Republic of Korea",
|
||||
"KR" : "Republic of Korea",
|
||||
"KW" : "Kuwait",
|
||||
"KY" : "Cayman Islands",
|
||||
"KZ" : "Kazakhstan",
|
||||
"LA" : "Lao People's Democratic Republic",
|
||||
"LB" : "Lebanon",
|
||||
"LC" : "Saint Lucia",
|
||||
"LI" : "Liechtenstein",
|
||||
"LK" : "Sri Lanka",
|
||||
"LR" : "Liberia",
|
||||
"LS" : "Lesotho",
|
||||
"LT" : "Lithuania",
|
||||
"LU" : "Luxembourg",
|
||||
"LV" : "Latvia",
|
||||
"LY" : "Libya",
|
||||
"MA" : "Morocco",
|
||||
"MC" : "Monaco",
|
||||
"MD" : "Republic of Moldova",
|
||||
"ME" : "Montenegro",
|
||||
"MF" : "Saint Martin (French part)",
|
||||
"MG" : "Madagascar",
|
||||
"MH" : "Marshall Islands",
|
||||
"MK" : "The Former Yugoslav Republic of Macedonia",
|
||||
"ML" : "Mali",
|
||||
"MM" : "Myanmar",
|
||||
"MN" : "Mongolia",
|
||||
"MO" : "Macao",
|
||||
"MP" : "Northern Mariana Islands",
|
||||
"MQ" : "Martinique",
|
||||
"MR" : "Mauritania",
|
||||
"MS" : "Montserrat",
|
||||
"MT" : "Malta",
|
||||
"MU" : "Mauritius",
|
||||
"MV" : "Maldives",
|
||||
"MW" : "Malawi",
|
||||
"MX" : "Mexico",
|
||||
"MY" : "Malaysia",
|
||||
"MZ" : "Mozambique",
|
||||
"NA" : "Namibia",
|
||||
"NC" : "New Caledonia",
|
||||
"NE" : "Niger",
|
||||
"NF" : "Norfolk Island",
|
||||
"NG" : "Nigeria",
|
||||
"NI" : "Nicaragua",
|
||||
"NL" : "Netherlands",
|
||||
"NO" : "Norway",
|
||||
"NP" : "Nepal",
|
||||
"NR" : "Nauru",
|
||||
"NU" : "Niue",
|
||||
"NZ" : "New Zealand",
|
||||
"OM" : "Oman",
|
||||
"PA" : "Panama",
|
||||
"PE" : "Peru",
|
||||
"PF" : "French Polynesia",
|
||||
"PG" : "Papua New Guinea",
|
||||
"PH" : "Philippines",
|
||||
"PK" : "Pakistan",
|
||||
"PL" : "Poland",
|
||||
"PM" : "Saint Pierre and Miquelon",
|
||||
"PN" : "Pitcairn",
|
||||
"PR" : "Puerto Rico",
|
||||
"PS" : "State of Palestine",
|
||||
"PT" : "Portugal",
|
||||
"PW" : "Palau",
|
||||
"PY" : "Paraguay",
|
||||
"QA" : "Qatar",
|
||||
"RE" : "Réunion",
|
||||
"RO" : "Romania",
|
||||
"RS" : "Serbia",
|
||||
"RU" : "Russian Federation",
|
||||
"RW" : "Rwanda",
|
||||
"SA" : "Saudi Arabia",
|
||||
"SB" : "Solomon Islands",
|
||||
"SC" : "Seychelles",
|
||||
"SD" : "Sudan",
|
||||
"SE" : "Sweden",
|
||||
"SG" : "Singapore",
|
||||
"SH" : "Saint Helena, Ascension and Tristan da Cunha",
|
||||
"SI" : "Slovenia",
|
||||
"SJ" : "Svalbard and Jan Mayen",
|
||||
"SK" : "Slovakia",
|
||||
"SL" : "Sierra Leone",
|
||||
"SM" : "San Marino",
|
||||
"SN" : "Senegal",
|
||||
"SO" : "Somalia",
|
||||
"SR" : "Suriname",
|
||||
"SS" : "South Sudan",
|
||||
"ST" : "Sao Tome and Principe",
|
||||
"SV" : "El Salvador",
|
||||
"SX" : "Sint Maarten",
|
||||
"SY" : "Syrian Arab Republic",
|
||||
"SZ" : "Swaziland",
|
||||
"TC" : "Turks and Caicos Islands",
|
||||
"TD" : "Chad",
|
||||
"TF" : "French Southern Territories",
|
||||
"TG" : "Togo",
|
||||
"TH" : "Thailand",
|
||||
"TJ" : "Tajikistan",
|
||||
"TK" : "Tokelau",
|
||||
"TL" : "Timor-Leste",
|
||||
"TM" : "Turkmenistan",
|
||||
"TN" : "Tunisia",
|
||||
"TO" : "Tonga",
|
||||
"TR" : "Turkey",
|
||||
"TT" : "Trinidad and Tobago",
|
||||
"TV" : "Tuvalu",
|
||||
"TW" : "Taiwan, Province of China",
|
||||
"TZ" : "United Republic of Tanzania",
|
||||
"UA" : "Ukraine",
|
||||
"UG" : "Uganda",
|
||||
"UM" : "United States Minor Outlying Islands",
|
||||
"US" : "United States",
|
||||
"UY" : "Uruguay",
|
||||
"UZ" : "Uzbekistan",
|
||||
"VA" : "Holy See (Vatican City State)",
|
||||
"VC" : "Saint Vincent and the Grenadines",
|
||||
"VE" : "Bolivarian Republic of Venezuela",
|
||||
"VG" : "British Virgin Islands",
|
||||
"VI" : "U.S. Virgin Islands",
|
||||
"VN" : "Viet Nam",
|
||||
"VU" : "Vanuatu",
|
||||
"WF" : "Wallis and Futuna",
|
||||
"WS" : "Samoa",
|
||||
"YE" : "Yemen",
|
||||
"YT" : "Mayotte",
|
||||
"ZA" : "South Africa",
|
||||
"ZM" : "Zambia",
|
||||
"ZW" : "Zimbabwe",
|
||||
}
|
||||
|
||||
# END Class isoCountry
|
||||
+16
-5
@@ -27,6 +27,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import logging
|
||||
import os
|
||||
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from nw.constants import nwAlert
|
||||
from nw.common import isHandle
|
||||
from nw.constants import nwItemLayout, nwItemClass
|
||||
@@ -48,6 +52,7 @@ class NWDoc():
|
||||
|
||||
# Internal Mapping
|
||||
self.makeAlert = self.theParent.makeAlert
|
||||
self.tr = partial(QCoreApplication.translate, "NWDoc")
|
||||
|
||||
return
|
||||
|
||||
@@ -111,7 +116,7 @@ class NWDoc():
|
||||
theText += inFile.read()
|
||||
|
||||
except Exception as e:
|
||||
self.makeAlert(["Failed to open document file.", str(e)], nwAlert.ERROR)
|
||||
self.makeAlert([self.tr("Failed to open document file."), str(e)], nwAlert.ERROR)
|
||||
# Note: Document must be cleared in case of an io error,
|
||||
# or else the auto-save or save will try to overwrite it
|
||||
# with an empty file. Return None to alert the caller.
|
||||
@@ -124,7 +129,9 @@ class NWDoc():
|
||||
return ""
|
||||
|
||||
if showStatus and not isOrphan:
|
||||
self.theParent.setStatus("Opened Document: %s" % self._theItem.itemName)
|
||||
self.theParent.setStatus(
|
||||
self.tr("Opened Document: {0}").format(self._theItem.itemName)
|
||||
)
|
||||
|
||||
return theText
|
||||
|
||||
@@ -158,7 +165,7 @@ class NWDoc():
|
||||
outFile.write(docMeta)
|
||||
outFile.write(docText)
|
||||
except Exception as e:
|
||||
self.makeAlert(["Could not save document.", str(e)], nwAlert.ERROR)
|
||||
self.makeAlert([self.tr("Could not save document."), str(e)], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
# If we're here, the file was successfully saved, so we can
|
||||
@@ -168,7 +175,9 @@ class NWDoc():
|
||||
os.rename(docTemp, docPath)
|
||||
|
||||
if self._theItem is not None:
|
||||
self.theParent.setStatus("Saved Document: %s" % self._theItem.itemName)
|
||||
self.theParent.setStatus(
|
||||
self.tr("Saved Document: {0}").format(self._theItem.itemName)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@@ -191,7 +200,9 @@ class NWDoc():
|
||||
os.unlink(chkFile)
|
||||
logger.debug("Deleted: %s" % chkFile)
|
||||
except Exception as e:
|
||||
self.makeAlert(["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
|
||||
|
||||
@@ -228,10 +228,6 @@ class NWIndex():
|
||||
|
||||
if self.indexBroken:
|
||||
self.clearIndex()
|
||||
self.theParent.makeAlert(
|
||||
"The project index is outdated or broken. Rebuilding index.",
|
||||
nwAlert.WARN
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+164
-123
@@ -31,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
|
||||
@@ -42,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__)
|
||||
@@ -97,11 +100,12 @@ class NWProject():
|
||||
self.notesWCount = 0 # Total number of words in note files
|
||||
self.doBackup = True # Run project backup on exit
|
||||
|
||||
# Set Defaults
|
||||
self.clearProject()
|
||||
|
||||
# Internal Mapping
|
||||
self.makeAlert = self.theParent.makeAlert
|
||||
self.tr = partial(QCoreApplication.translate, "NWProject")
|
||||
|
||||
# Set Defaults
|
||||
self.clearProject()
|
||||
|
||||
return
|
||||
|
||||
@@ -157,7 +161,7 @@ class NWProject():
|
||||
trashHandle = self.projTree.trashRoot()
|
||||
if trashHandle is None:
|
||||
newItem = NWItem(self)
|
||||
newItem.setName("Trash")
|
||||
newItem.setName(self.tr("Trash"))
|
||||
newItem.setType(nwItemType.TRASH)
|
||||
newItem.setClass(nwItemClass.TRASH)
|
||||
self.projTree.append(None, None, newItem)
|
||||
@@ -197,7 +201,7 @@ class NWProject():
|
||||
self.autoReplace = {}
|
||||
self.titleFormat = {
|
||||
"title" : r"%title%",
|
||||
"chapter" : r"Chapter %ch%: %title%",
|
||||
"chapter" : self.tr(r"Chapter %ch%: %title%"),
|
||||
"unnumbered" : r"%title%",
|
||||
"scene" : r"* * *",
|
||||
"section" : r"",
|
||||
@@ -205,15 +209,15 @@ class NWProject():
|
||||
self.spellCheck = False
|
||||
self.autoOutline = True
|
||||
self.statusItems = NWStatus()
|
||||
self.statusItems.addEntry("New", (100, 100, 100))
|
||||
self.statusItems.addEntry("Note", (200, 50, 0))
|
||||
self.statusItems.addEntry("Draft", (200, 150, 0))
|
||||
self.statusItems.addEntry("Finished", (50, 200, 0))
|
||||
self.statusItems.addEntry(self.tr("New"), (100, 100, 100))
|
||||
self.statusItems.addEntry(self.tr("Note"), (200, 50, 0))
|
||||
self.statusItems.addEntry(self.tr("Draft"), (200, 150, 0))
|
||||
self.statusItems.addEntry(self.tr("Finished"), (50, 200, 0))
|
||||
self.importItems = NWStatus()
|
||||
self.importItems.addEntry("New", (100, 100, 100))
|
||||
self.importItems.addEntry("Minor", (200, 50, 0))
|
||||
self.importItems.addEntry("Major", (200, 150, 0))
|
||||
self.importItems.addEntry("Main", (50, 200, 0))
|
||||
self.importItems.addEntry(self.tr("New"), (100, 100, 100))
|
||||
self.importItems.addEntry(self.tr("Minor"), (200, 50, 0))
|
||||
self.importItems.addEntry(self.tr("Major"), (200, 150, 0))
|
||||
self.importItems.addEntry(self.tr("Main"), (50, 200, 0))
|
||||
self.lastEdited = None
|
||||
self.lastViewed = None
|
||||
self.lastWCount = 0
|
||||
@@ -239,7 +243,7 @@ class NWProject():
|
||||
|
||||
# Project Settings
|
||||
projPath = projData.get("projPath", None)
|
||||
projName = projData.get("projName", "New Project")
|
||||
projName = projData.get("projName", self.tr("New Project"))
|
||||
projTitle = projData.get("projTitle", "")
|
||||
projAuthors = projData.get("projAuthors", "")
|
||||
|
||||
@@ -256,7 +260,7 @@ class NWProject():
|
||||
|
||||
titlePage = "# %s\n\n" % (self.bookTitle if self.bookTitle else self.projName)
|
||||
if self.bookAuthors:
|
||||
titlePage = "%sBy %s\n" % (titlePage, ", ".join(self.bookAuthors))
|
||||
titlePage = "%s%s %s\n" % (titlePage, self.tr("By"), self.getAuthors())
|
||||
|
||||
# Document object for writing files
|
||||
aDoc = NWDoc(self, self.theParent)
|
||||
@@ -265,14 +269,14 @@ class NWProject():
|
||||
# Creating a minimal project with a few root folders and a
|
||||
# single chapter folder with a single file.
|
||||
xHandle = {}
|
||||
xHandle[1] = self.newRoot("Novel", nwItemClass.NOVEL)
|
||||
xHandle[2] = self.newRoot("Plot", nwItemClass.PLOT)
|
||||
xHandle[3] = self.newRoot("Characters", nwItemClass.CHARACTER)
|
||||
xHandle[4] = self.newRoot("World", nwItemClass.WORLD)
|
||||
xHandle[5] = self.newFile("Title Page", nwItemClass.NOVEL, xHandle[1])
|
||||
xHandle[6] = self.newFolder("New Chapter", nwItemClass.NOVEL, xHandle[1])
|
||||
xHandle[7] = self.newFile("New Chapter", nwItemClass.NOVEL, xHandle[6])
|
||||
xHandle[8] = self.newFile("New Scene", nwItemClass.NOVEL, xHandle[6])
|
||||
xHandle[1] = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL)
|
||||
xHandle[2] = self.newRoot(self.tr("Plot"), nwItemClass.PLOT)
|
||||
xHandle[3] = self.newRoot(self.tr("Characters"), nwItemClass.CHARACTER)
|
||||
xHandle[4] = self.newRoot(self.tr("World"), nwItemClass.WORLD)
|
||||
xHandle[5] = self.newFile(self.tr("Title Page"), nwItemClass.NOVEL, xHandle[1])
|
||||
xHandle[6] = self.newFolder(self.tr("New Chapter"), nwItemClass.NOVEL, xHandle[1])
|
||||
xHandle[7] = self.newFile(self.tr("New Chapter"), nwItemClass.NOVEL, xHandle[6])
|
||||
xHandle[8] = self.newFile(self.tr("New Scene"), nwItemClass.NOVEL, xHandle[6])
|
||||
|
||||
self.projTree.setFileItemLayout(xHandle[5], nwItemLayout.TITLE)
|
||||
self.projTree.setFileItemLayout(xHandle[7], nwItemLayout.CHAPTER)
|
||||
@@ -282,11 +286,11 @@ class NWProject():
|
||||
aDoc.clearDocument()
|
||||
|
||||
aDoc.openDocument(xHandle[7], showStatus=False)
|
||||
aDoc.saveDocument("## New Chapter\n\n")
|
||||
aDoc.saveDocument("## %s\n\n" % self.tr("New Chapter"))
|
||||
aDoc.clearDocument()
|
||||
|
||||
aDoc.openDocument(xHandle[8], showStatus=False)
|
||||
aDoc.saveDocument("### New Scene\n\n")
|
||||
aDoc.saveDocument("### %s\n\n" % self.tr("New Scene"))
|
||||
aDoc.clearDocument()
|
||||
|
||||
elif popCustom:
|
||||
@@ -295,13 +299,13 @@ class NWProject():
|
||||
# wizard's custom page.
|
||||
|
||||
# Create root folders
|
||||
nHandle = self.newRoot("Novel", nwItemClass.NOVEL)
|
||||
nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL)
|
||||
for newRoot in projData.get("addRoots", []):
|
||||
if newRoot in nwItemClass:
|
||||
self.newRoot(nwLabels.CLASS_NAME[newRoot], newRoot)
|
||||
self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot)
|
||||
|
||||
# Create a title page
|
||||
tHandle = self.newFile("Title Page", nwItemClass.NOVEL, nHandle)
|
||||
tHandle = self.newFile(self.tr("Title Page"), nwItemClass.NOVEL, nHandle)
|
||||
self.projTree.setFileItemLayout(tHandle, nwItemLayout.TITLE)
|
||||
|
||||
aDoc.openDocument(tHandle, showStatus=False)
|
||||
@@ -316,7 +320,7 @@ class NWProject():
|
||||
# Create chapters
|
||||
if numChapters > 0:
|
||||
for ch in range(numChapters):
|
||||
chTitle = "Chapter %d" % (ch+1)
|
||||
chTitle = self.tr("Chapter {0}").format(f"{ch+1:d}")
|
||||
pHandle = nHandle
|
||||
if chFolders:
|
||||
pHandle = self.newFolder(chTitle, nwItemClass.NOVEL, nHandle)
|
||||
@@ -331,7 +335,7 @@ class NWProject():
|
||||
# Create chapter scenes
|
||||
if numScenes > 0:
|
||||
for sc in range(numScenes):
|
||||
scTitle = "Scene %d.%d" % (ch+1, sc+1)
|
||||
scTitle = self.tr("Scene {0}").format(f"{ch+1:d}.{sc+1:d}")
|
||||
sHandle = self.newFile(scTitle, nwItemClass.NOVEL, pHandle)
|
||||
|
||||
aDoc.openDocument(sHandle, showStatus=False)
|
||||
@@ -341,7 +345,7 @@ class NWProject():
|
||||
# Create scenes (no chapters)
|
||||
elif numScenes > 0:
|
||||
for sc in range(numScenes):
|
||||
scTitle = "Scene %d" % (sc+1)
|
||||
scTitle = self.tr("Scene {0}").format(f"{sc+1:d}")
|
||||
sHandle = self.newFile(scTitle, nwItemClass.NOVEL, nHandle)
|
||||
|
||||
aDoc.openDocument(sHandle, showStatus=False)
|
||||
@@ -365,7 +369,7 @@ class NWProject():
|
||||
if not os.path.isfile(fileName):
|
||||
fileName = os.path.join(fileName, nwFiles.PROJ_FILE)
|
||||
if not os.path.isfile(fileName):
|
||||
self.makeAlert("File not found: %s" % fileName, nwAlert.ERROR)
|
||||
self.makeAlert(self.tr("File not found: {0}").format(fileName), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
self.clearProject()
|
||||
@@ -414,16 +418,20 @@ class NWProject():
|
||||
try:
|
||||
nwXML = etree.parse(fileName)
|
||||
except Exception as e:
|
||||
self.makeAlert(["Failed to parse project xml.", str(e)], nwAlert.ERROR)
|
||||
self.makeAlert([self.tr("Failed to parse project xml."), str(e)], nwAlert.ERROR)
|
||||
|
||||
# Trying to open backup file instead
|
||||
backFile = fileName[:-3]+"bak"
|
||||
if os.path.isfile(backFile):
|
||||
self.makeAlert("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(["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:
|
||||
@@ -433,9 +441,9 @@ class NWProject():
|
||||
xRoot = nwXML.getroot()
|
||||
nwxRoot = xRoot.tag
|
||||
|
||||
appVersion = xRoot.attrib.get("appVersion", "Unknown")
|
||||
appVersion = xRoot.attrib.get("appVersion", self.tr("Unknown"))
|
||||
hexVersion = xRoot.attrib.get("hexVersion", "0x0")
|
||||
fileVersion = xRoot.attrib.get("fileVersion", "Unknown")
|
||||
fileVersion = xRoot.attrib.get("fileVersion", self.tr("Unknown"))
|
||||
|
||||
# The following are deprecated and will be removed
|
||||
# The settings have been moved to the <project> tag
|
||||
@@ -451,7 +459,7 @@ class NWProject():
|
||||
|
||||
if not nwxRoot == "novelWriterXML":
|
||||
self.makeAlert(
|
||||
"Project file does not appear to be a novelWriterXML file.",
|
||||
self.tr("Project file does not appear to be a novelWriterXML file."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
self.clearProject()
|
||||
@@ -470,24 +478,32 @@ class NWProject():
|
||||
# read the file. Introduced in version 0.10.
|
||||
|
||||
if fileVersion == "1.0":
|
||||
msgYes = self.theParent.askQuestion("Old Project Version", (
|
||||
"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?<br><br>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."
|
||||
))
|
||||
msgYes = self.theParent.askQuestion(
|
||||
self.tr("Old Project Version"),
|
||||
"%s<br><br>%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."
|
||||
)
|
||||
)
|
||||
)
|
||||
if not msgYes:
|
||||
self.clearProject()
|
||||
return False
|
||||
|
||||
elif fileVersion != "1.1" and fileVersion != "1.2":
|
||||
self.makeAlert((
|
||||
"Unknown or unsupported novelWriter project file format. "
|
||||
"The project cannot be opened by this version of novelWriter. "
|
||||
"The file was saved with novelWriter version {vers:s}."
|
||||
).format(
|
||||
vers = 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
|
||||
@@ -496,14 +512,15 @@ class NWProject():
|
||||
# =========================
|
||||
|
||||
if hexToInt(hexVersion) > hexToInt(nw.__hexversion__):
|
||||
msgYes = self.theParent.askQuestion("Version Conflict", (
|
||||
"This project was saved by a newer version of novelWriter, version %s. "
|
||||
"This is version %s. 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?"
|
||||
) % (
|
||||
appVersion, nw.__version__
|
||||
))
|
||||
msgYes = self.theParent.askQuestion(
|
||||
self.tr("Version Conflict"),
|
||||
self.tr(
|
||||
"This project was saved by a newer version of novelWriter, version "
|
||||
"{0}. This is version {1}. 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(appVersion, nw.__version__)
|
||||
)
|
||||
if not msgYes:
|
||||
self.clearProject()
|
||||
return False
|
||||
@@ -602,7 +619,7 @@ class NWProject():
|
||||
self.mainConf.updateRecentCache(self.projPath, self.projName, self.lastWCount, time())
|
||||
self.mainConf.saveRecentCache()
|
||||
|
||||
self.theParent.setStatus("Opened Project: %s" % self.projName)
|
||||
self.theParent.setStatus(self.tr("Opened Project: {0}").format(self.projName))
|
||||
|
||||
self._scanProjectFolder()
|
||||
|
||||
@@ -623,7 +640,7 @@ class NWProject():
|
||||
"""
|
||||
if self.projPath is None:
|
||||
self.makeAlert(
|
||||
"Project path not set, cannot save project.", nwAlert.ERROR
|
||||
self.tr("Project path not set, cannot save project."), nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -702,7 +719,7 @@ class NWProject():
|
||||
xml_declaration = True
|
||||
))
|
||||
except Exception as e:
|
||||
self.makeAlert(["Failed to save project.", str(e)], nwAlert.ERROR)
|
||||
self.makeAlert([self.tr("Failed to save project."), str(e)], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
# If we're here, the file was successfully saved,
|
||||
@@ -721,7 +738,7 @@ class NWProject():
|
||||
self.mainConf.saveRecentCache()
|
||||
|
||||
self._writeLockFile()
|
||||
self.theParent.setStatus("Saved Project: %s" % self.projName)
|
||||
self.theParent.setStatus(self.tr("Saved Project: {0}").format(self.projName))
|
||||
self.setProjectChanged(False)
|
||||
|
||||
return True
|
||||
@@ -773,27 +790,33 @@ class NWProject():
|
||||
return False
|
||||
|
||||
logger.info("Backing up project")
|
||||
self.theParent.setStatus("Backing up project ...")
|
||||
self.theParent.setStatus(self.tr("Backing up project ..."))
|
||||
|
||||
if self.mainConf.backupPath is None or self.mainConf.backupPath == "":
|
||||
self.theParent.makeAlert((
|
||||
"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((
|
||||
"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((
|
||||
"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)
|
||||
@@ -804,20 +827,22 @@ class NWProject():
|
||||
logger.debug("Created folder %s" % baseDir)
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Could not create backup folder.", str(e)],
|
||||
[self.tr("Could not create backup folder."), str(e)],
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
if os.path.commonpath([self.projPath, baseDir]) == self.projPath:
|
||||
self.theParent.makeAlert((
|
||||
"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 = "Backup from %s" % formatTimeStamp(time(), fileSafe=True)
|
||||
archName = self.tr("Backup from {0}").format(formatTimeStamp(time(), fileSafe=True))
|
||||
baseName = os.path.join(baseDir, archName)
|
||||
|
||||
try:
|
||||
@@ -827,18 +852,21 @@ class NWProject():
|
||||
logger.info("Backup written to: %s" % archName)
|
||||
if doNotify:
|
||||
self.theParent.makeAlert(
|
||||
"Backup archive file written to: %s.zip" % os.path.join(cleanName, archName),
|
||||
nwAlert.INFO
|
||||
self.tr(
|
||||
"Backup archive file written to: {0}"
|
||||
).format(
|
||||
f"{os.path.join(cleanName, archName)}.zip"
|
||||
), nwAlert.INFO
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Could not write backup archive.", str(e)],
|
||||
[self.tr("Could not write backup archive."), str(e)],
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
self.theParent.setStatus("Project backed up to '%s.zip'" % baseName)
|
||||
self.theParent.setStatus(self.tr("Project backed up to '{0}'").format(f"{baseName}.zip"))
|
||||
|
||||
return True
|
||||
|
||||
@@ -865,7 +893,7 @@ class NWProject():
|
||||
isSuccess = True
|
||||
except Exception as e:
|
||||
self.makeAlert(
|
||||
["Failed to create a new example project.", str(e)], nwAlert.ERROR
|
||||
[self.tr("Failed to create a new example project."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
|
||||
elif os.path.isdir(srcSample):
|
||||
@@ -887,14 +915,16 @@ class NWProject():
|
||||
|
||||
except Exception as e:
|
||||
self.makeAlert(
|
||||
["Failed to create a new example project.", str(e)], nwAlert.ERROR
|
||||
[self.tr("Failed to create a new example project."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
|
||||
else:
|
||||
self.makeAlert((
|
||||
"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()
|
||||
@@ -925,16 +955,18 @@ class NWProject():
|
||||
logger.debug("Created folder %s" % projPath)
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert((
|
||||
["Could not create new project folder.", str(e)]
|
||||
[self.tr("Could not create new project folder."), str(e)]
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
if os.path.isdir(projPath):
|
||||
if os.listdir(self.projPath):
|
||||
self.theParent.makeAlert((
|
||||
"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()
|
||||
@@ -981,17 +1013,21 @@ class NWProject():
|
||||
self.doBackup = doBackup
|
||||
if doBackup:
|
||||
if not os.path.isdir(self.mainConf.backupPath):
|
||||
self.theParent.makeAlert((
|
||||
"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((
|
||||
"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
|
||||
@@ -1120,8 +1156,8 @@ class NWProject():
|
||||
if nAuth == 1:
|
||||
authString = self.bookAuthors[0]
|
||||
elif nAuth > 1:
|
||||
authString = "%s and %s" % (
|
||||
", ".join(self.bookAuthors[0:-1]), self.bookAuthors[-1]
|
||||
authString = "%s %s %s" % (
|
||||
", ".join(self.bookAuthors[0:-1]), self.tr("and"), self.bookAuthors[-1]
|
||||
)
|
||||
|
||||
return authString
|
||||
@@ -1330,7 +1366,7 @@ class NWProject():
|
||||
# Report status
|
||||
if len(orphanFiles) > 0:
|
||||
self.makeAlert(
|
||||
"Found %d orphaned file(s) in project folder." % len(orphanFiles),
|
||||
self.tr("Found {0} orphaned file(s) in project folder.").format(len(orphanFiles)),
|
||||
nwAlert.WARN
|
||||
)
|
||||
else:
|
||||
@@ -1341,6 +1377,7 @@ class NWProject():
|
||||
aDoc = NWDoc(self, self.theParent)
|
||||
nOrph = 0
|
||||
noWhere = False
|
||||
oPrefix = self.tr("Recovered")
|
||||
for oHandle in orphanFiles:
|
||||
|
||||
# Look for meta data
|
||||
@@ -1352,10 +1389,12 @@ class NWProject():
|
||||
oName, oParent, oClass, oLayout = aDoc.getMeta()
|
||||
|
||||
if oName:
|
||||
oName = "Recovered: %s" % oName.lstrip("Recovered: ")
|
||||
oName = self.tr("[{0}] {1}").format(
|
||||
oPrefix, oName.replace("[%s]" % oPrefix, "").strip()
|
||||
)
|
||||
else:
|
||||
nOrph += 1
|
||||
oName = "Recovered File %d" % nOrph
|
||||
oName = self.tr("Recovered File {0}").format(nOrph)
|
||||
|
||||
# Recover file meta data
|
||||
if oClass is None:
|
||||
@@ -1382,10 +1421,12 @@ class NWProject():
|
||||
self.projTree.append(oHandle, oParent, orphItem)
|
||||
|
||||
if noWhere:
|
||||
self.makeAlert((
|
||||
"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
|
||||
|
||||
@@ -1432,7 +1473,7 @@ class NWProject():
|
||||
"""
|
||||
theData = os.path.join(self.projPath, theFolder)
|
||||
if not os.path.isdir(theData):
|
||||
errList.append("Not a folder: %s" % theData)
|
||||
errList.append(self.tr("Not a folder: {0}").format(theData))
|
||||
return errList
|
||||
|
||||
logger.info("Old data folder %s found" % theFolder)
|
||||
@@ -1455,7 +1496,7 @@ class NWProject():
|
||||
logger.info("Moved file: %s" % theFile)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except Exception:
|
||||
errList.append("Could not move: %s" % theFile)
|
||||
errList.append(self.tr("Could not move: {0}").format(theFile))
|
||||
logger.error("Could not move: %s" % theFile)
|
||||
nw.logException()
|
||||
|
||||
@@ -1464,7 +1505,7 @@ class NWProject():
|
||||
os.unlink(theFile)
|
||||
logger.info("Deleted file: %s" % theFile)
|
||||
except Exception:
|
||||
errList.append("Could not delete: %s" % theFile)
|
||||
errList.append(self.tr("Could not delete: {0}").format(theFile))
|
||||
logger.error("Could not delete: %s" % theFile)
|
||||
nw.logException()
|
||||
|
||||
@@ -1477,10 +1518,10 @@ class NWProject():
|
||||
# ==================
|
||||
try:
|
||||
os.rmdir(theData)
|
||||
logger.info("Removed folder: %s" % theFolder)
|
||||
logger.info("Deleted folder: %s" % theFolder)
|
||||
except Exception:
|
||||
errList.append("Failed to remove: %s" % theFolder)
|
||||
logger.error("Failed to remove: %s" % theFolder)
|
||||
errList.append(self.tr("Could not delete: {0}").format(theFolder))
|
||||
logger.error("Could not delete: %s" % theFolder)
|
||||
nw.logException()
|
||||
|
||||
return errList
|
||||
@@ -1491,7 +1532,7 @@ class NWProject():
|
||||
"""
|
||||
theJunk = os.path.join(self.projPath, "junk")
|
||||
if not self._checkFolder(theJunk):
|
||||
return "Could not make folder: %s" % theJunk
|
||||
return self.tr("Could not make folder: {0}").format(theJunk)
|
||||
|
||||
theSrc = os.path.join(theDir, theItem)
|
||||
theDst = os.path.join(theJunk, theItem)
|
||||
@@ -1502,7 +1543,7 @@ class NWProject():
|
||||
except Exception:
|
||||
logger.error("Could not move item %s to junk." % theSrc)
|
||||
nw.logException()
|
||||
return "Could not move item %s to junk." % theSrc
|
||||
return self.tr("Could not move item {0} to {1}.").format(theSrc, theJunk)
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
+4
-17
@@ -29,8 +29,6 @@ import logging
|
||||
import os
|
||||
import difflib
|
||||
|
||||
from nw.constants import nwConst, isoLanguage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# =============================================================================================== #
|
||||
@@ -89,16 +87,6 @@ class NWSpellCheck():
|
||||
"""
|
||||
return "", ""
|
||||
|
||||
@staticmethod
|
||||
def expandLanguage(spTag):
|
||||
"""Translate a language tag to something more user friendly.
|
||||
"""
|
||||
spBits = spTag.split("_")
|
||||
spLang = isoLanguage.ISO_639_1.get(spBits[0], spBits[0])
|
||||
if len(spBits) > 1:
|
||||
spLang += " (%s)" % spBits[1]
|
||||
return spLang
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
@@ -196,10 +184,10 @@ class NWSpellEnchant(NWSpellCheck):
|
||||
try:
|
||||
import enchant
|
||||
for spTag, spProvider in enchant.list_dicts():
|
||||
spName = "%s [%s]" % (self.expandLanguage(spTag), spProvider.name)
|
||||
retList.append((spTag, spName))
|
||||
retList.append((spTag, spProvider.name))
|
||||
except Exception:
|
||||
logger.error("Failed to list languages for enchant spell checking")
|
||||
|
||||
return retList
|
||||
|
||||
def describeDict(self):
|
||||
@@ -332,8 +320,7 @@ class NWSpellSimple(NWSpellCheck):
|
||||
if fExt != ".dict":
|
||||
continue
|
||||
|
||||
spName = "%s [%s]" % (self.expandLanguage(fRoot), nwConst.SP_INTERNAL)
|
||||
retList.append((fRoot, spName))
|
||||
retList.append((fRoot, "difflib"))
|
||||
|
||||
return retList
|
||||
|
||||
@@ -341,6 +328,6 @@ class NWSpellSimple(NWSpellCheck):
|
||||
"""Return the tag and provider of the currently loaded
|
||||
dictionary.
|
||||
"""
|
||||
return self.theLang, nwConst.SP_INTERNAL
|
||||
return self.theLang, ""
|
||||
|
||||
# END Class NWSpellSimple
|
||||
|
||||
+9
-3
@@ -406,9 +406,13 @@ class ToHtml(Tokenizer):
|
||||
"""Apply HTML formatting to synopsis.
|
||||
"""
|
||||
if self.genMode == self.M_PREVIEW:
|
||||
return "<p class='comment'><span class='synopsis'>Synopsis:</span> %s</p>\n" % tText
|
||||
return "<p class='comment'><span class='synopsis'>%s:</span> %s</p>\n" % (
|
||||
self._trSynopsis, tText
|
||||
)
|
||||
else:
|
||||
return "<p class='synopsis'><strong>Synopsis:</strong> %s</p>\n" % tText
|
||||
return "<p class='synopsis'><strong>%s:</strong> %s</p>\n" % (
|
||||
self._trSynopsis, tText
|
||||
)
|
||||
|
||||
def _formatComments(self, tText):
|
||||
"""Apply HTML formatting to comments.
|
||||
@@ -416,7 +420,9 @@ class ToHtml(Tokenizer):
|
||||
if self.genMode == self.M_PREVIEW:
|
||||
return "<p class='comment'>%s</p>\n" % tText
|
||||
else:
|
||||
return "<p class='comment'><strong>Comment:</strong> %s</p>\n" % tText
|
||||
return "<p class='comment'><strong>%s:</strong> %s</p>\n" % (
|
||||
self._trComment, tText
|
||||
)
|
||||
|
||||
def _formatKeywords(self, tText):
|
||||
"""Apply HTML formatting to keywords.
|
||||
|
||||
+20
-6
@@ -28,7 +28,9 @@ import logging
|
||||
import re
|
||||
|
||||
from operator import itemgetter
|
||||
from PyQt5.QtCore import QRegularExpression
|
||||
from functools import partial
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||
|
||||
from nw.core.document import NWDoc
|
||||
from nw.core.tools import numberToWord, numberToRoman
|
||||
@@ -141,6 +143,18 @@ class Tokenizer():
|
||||
# Error Handling
|
||||
self.errData = []
|
||||
|
||||
# Internal Mappings
|
||||
self.tr = partial(QCoreApplication.translate, "Tokenizer")
|
||||
|
||||
# Localisation
|
||||
self._trSynopsis = self.tr("Synopsis")
|
||||
self._trComment = self.tr("Comment")
|
||||
self._trNotes = self.tr("Notes")
|
||||
|
||||
self._spellLang = self.theProject.projLang
|
||||
if self._spellLang is None:
|
||||
self._spellLang = self.theParent.mainConf.spellLanguage
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
@@ -249,7 +263,7 @@ class Tokenizer():
|
||||
if theItem.itemType != nwItemType.ROOT:
|
||||
return False
|
||||
|
||||
theTitle = "Notes: %s" % 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
|
||||
@@ -278,10 +292,10 @@ class Tokenizer():
|
||||
|
||||
docSize = len(self.theText)
|
||||
if docSize > nwConst.MAX_DOCSIZE:
|
||||
errVal = "Document '%s' is too big (%.2f MB). Skipping." % (
|
||||
self.theItem.itemName, docSize/1.0e6
|
||||
errVal = self.tr("Document '{0}' is too big ({1} MB). Skipping.").format(
|
||||
self.theItem.itemName, f"{docSize/1.0e6:.2f}"
|
||||
)
|
||||
self.theText = "# ERROR\n\n%s\n\n" % errVal
|
||||
self.theText = "# %s\n\n%s\n\n" % (self.tr("ERROR"), errVal)
|
||||
self.errData.append(errVal)
|
||||
|
||||
self.isNone = self.theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
@@ -653,7 +667,7 @@ class Tokenizer():
|
||||
theTitle = theTitle.replace(r"%sc%", str(self.numChScene))
|
||||
theTitle = theTitle.replace(r"%sca%", str(self.numAbsScene))
|
||||
if r"%chw%" in theTitle:
|
||||
theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter, "en"))
|
||||
theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter, self._spellLang))
|
||||
if r"%chi%" in theTitle:
|
||||
theTitle = theTitle.replace(r"%chi%", numberToRoman(self.numChapter, True))
|
||||
if r"%chI%" in theTitle:
|
||||
|
||||
+91
-41
@@ -120,35 +120,40 @@ def numberToRoman(numVal, isLower=False):
|
||||
return romNum.lower() if isLower else romNum
|
||||
|
||||
# =============================================================================================== #
|
||||
# Convert an Integer to a Word Number
|
||||
# Convert an Integer to a Number String
|
||||
# =============================================================================================== #
|
||||
|
||||
def numberToWord(numVal, theLanguage):
|
||||
def numberToWord(numVal, theLang):
|
||||
"""Wrapper for converting numbers to words for chapter headings.
|
||||
"""
|
||||
if not isinstance(numVal, int):
|
||||
return "[NaN]"
|
||||
|
||||
if numVal < 0:
|
||||
return "[<0]"
|
||||
|
||||
if numVal > 999:
|
||||
return "[>999]"
|
||||
|
||||
numWord = ""
|
||||
if theLanguage == "en":
|
||||
numWord = _numberToWordEN(numVal)
|
||||
theCode = theLang.split("_")[0]
|
||||
if theCode == "en":
|
||||
numWord = _numberToWord_EN(numVal)
|
||||
elif theCode in ("nb", "nn"):
|
||||
numWord = _numberToWord_NO(numVal, theCode)
|
||||
else:
|
||||
numWord = _numberToWordEN(numVal)
|
||||
# Default to return the number as a string
|
||||
numWord = str(numVal)
|
||||
|
||||
return numWord
|
||||
|
||||
def _numberToWordEN(numVal):
|
||||
def _numberToWord_EN(numVal):
|
||||
"""Convert numbers to English words.
|
||||
"""
|
||||
oneWord = ""
|
||||
tenWord = ""
|
||||
hunWord = ""
|
||||
|
||||
if not isinstance(numVal, int):
|
||||
return "[NaN]"
|
||||
|
||||
if numVal < 0:
|
||||
return "[Negative]"
|
||||
|
||||
if numVal > 999:
|
||||
return "[Out of Range]"
|
||||
|
||||
if numVal == 0:
|
||||
return "Zero"
|
||||
|
||||
@@ -156,38 +161,83 @@ def _numberToWordEN(numVal):
|
||||
tenVal = (numVal - oneVal) % 100
|
||||
hunVal = (numVal - tenVal - oneVal) % 1000
|
||||
|
||||
theHundreds = {
|
||||
100: "One Hundred", 200: "Two Hundred", 300: "Three Hundred",
|
||||
400: "Four Hundred", 500: "Five Hundred", 600: "Six Hundred",
|
||||
700: "Seven Hundred", 800: "Eight Hundred", 900: "Nine Hundred",
|
||||
}
|
||||
theTens = {
|
||||
20: "Twenty", 30: "Thirty", 40: "Forty", 50: "Fifty",
|
||||
60: "Sixty", 70: "Seventy", 80: "Eighty", 90: "Ninety",
|
||||
}
|
||||
theTeens = {
|
||||
0: "Ten", 1: "Eleven", 2: "Twelve", 3: "Thirteen", 4: "Fourteen",
|
||||
5: "Fifteen", 6: "Sixteen", 7: "Seventeen", 8: "Eighteen", 9: "Nineteen",
|
||||
}
|
||||
theOnes = {
|
||||
0: "", 1: "One", 2: "Two", 3: "Three", 4: "Four",
|
||||
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine",
|
||||
theWords = {
|
||||
0: "", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five",
|
||||
6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10: "Ten",
|
||||
11: "Eleven", 12: "Twelve", 13: "Thirteen", 14: "Fourteen",
|
||||
15: "Fifteen", 16: "Sixteen", 17: "Seventeen", 18: "Eighteen",
|
||||
19: "Nineteen", 20: "Twenty", 30: "Thirty", 40: "Forty",
|
||||
50: "Fifty", 60: "Sixty", 70: "Seventy", 80: "Eighty",
|
||||
90: "Ninety", 100: "One Hundred", 200: "Two Hundred",
|
||||
300: "Three Hundred", 400: "Four Hundred", 500: "Five Hundred",
|
||||
600: "Six Hundred", 700: "Seven Hundred", 800: "Eight Hundred",
|
||||
900: "Nine Hundred",
|
||||
}
|
||||
|
||||
retVale = ""
|
||||
hunWord = theHundreds.get(hunVal, "")
|
||||
retVal = ""
|
||||
hunWord = theWords.get(hunVal, "")
|
||||
if tenVal == 10:
|
||||
oneWord = theTeens.get(oneVal, "")
|
||||
retVale = f"{hunWord} {oneWord}".strip()
|
||||
oneWord = theWords.get(oneVal+10, "")
|
||||
retVal = f"{hunWord} {oneWord}".strip()
|
||||
else:
|
||||
oneWord = theOnes.get(oneVal, "")
|
||||
oneWord = theWords.get(oneVal, "")
|
||||
if tenVal == 0:
|
||||
retVale = f"{hunWord} {oneWord}".strip()
|
||||
retVal = f"{hunWord} {oneWord}".strip()
|
||||
else:
|
||||
tenWord = theTens.get(tenVal, "")
|
||||
tenWord = theWords.get(tenVal, "")
|
||||
if oneVal == 0:
|
||||
retVale = f"{hunWord} {tenWord}".strip()
|
||||
retVal = f"{hunWord} {tenWord}".strip()
|
||||
else:
|
||||
retVale = f"{hunWord} {tenWord}-{oneWord}".strip()
|
||||
retVal = f"{hunWord} {tenWord}-{oneWord}".strip()
|
||||
|
||||
return retVale
|
||||
return retVal
|
||||
|
||||
def _numberToWord_NO(numVal, theCode):
|
||||
"""Convert numbers to Norwegian words.
|
||||
"""
|
||||
oneWord = ""
|
||||
tenWord = ""
|
||||
hunWord = ""
|
||||
|
||||
if numVal == 0:
|
||||
return "null"
|
||||
|
||||
oneVal = numVal % 10
|
||||
tenVal = (numVal - oneVal) % 100
|
||||
hunVal = (numVal - tenVal - oneVal) % 1000
|
||||
|
||||
theWords = {
|
||||
0: "", 1: "én", 2: "to", 3: "tre", 4: "fire", 5: "fem", 6: "seks",
|
||||
7: "sju", 8: "åtte", 9: "ni", 10: "ti", 11: "elleve", 12: "tolv",
|
||||
13: "tretten", 14: "fjorten", 15: "femten", 16: "seksten", 17: "sytten",
|
||||
18: "atten", 19: "nitten", 20: "tjue", 30: "tretti", 40: "førti",
|
||||
50: "femti", 60: "seksti", 70: "sytti", 80: "åtti", 90: "nitti",
|
||||
100: "ett hundre", 200: "to hundre", 300: "tre hundre", 400: "fire hundre",
|
||||
500: "fem hundre", 600: "seks hundre", 700: "sju hundre",
|
||||
800: "åtte hundre", 900: "ni hundre",
|
||||
}
|
||||
|
||||
if theCode == "nn":
|
||||
theWords[1] = "ein"
|
||||
theWords[100] = "eitt hundre"
|
||||
|
||||
retVal = ""
|
||||
hunWord = theWords.get(hunVal, "")
|
||||
if tenVal == 10:
|
||||
oneWord = theWords.get(oneVal+10, "")
|
||||
sepVal = " og " if hunWord and oneWord else " "
|
||||
retVal = f"{hunWord}{sepVal}{oneWord}"
|
||||
else:
|
||||
oneWord = theWords.get(oneVal, "")
|
||||
if tenVal == 0:
|
||||
sepVal = " og " if hunWord and oneWord else " "
|
||||
retVal = f"{hunWord}{sepVal}{oneWord}".strip()
|
||||
else:
|
||||
tenWord = theWords.get(tenVal, "")
|
||||
sepVal = " og " if hunWord and tenWord else " "
|
||||
if oneVal == 0:
|
||||
retVal = f"{hunWord}{sepVal}{tenWord}".strip()
|
||||
else:
|
||||
retVal = f"{hunWord}{sepVal}{tenWord}{oneWord}".strip()
|
||||
|
||||
return retVal.strip()
|
||||
|
||||
@@ -68,6 +68,7 @@ class NWErrorMessage(QDialog):
|
||||
self.msgBody.setReadOnly(True)
|
||||
|
||||
self.btnBox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
self.btnBox.button(QDialogButtonBox.Close).setText(self.tr("Close"))
|
||||
self.btnBox.rejected.connect(self._doClose)
|
||||
|
||||
# Assemble
|
||||
|
||||
+63
-66
@@ -55,7 +55,7 @@ class GuiAbout(QDialog):
|
||||
self.innerBox = QHBoxLayout()
|
||||
self.innerBox.setSpacing(self.mainConf.pxInt(16))
|
||||
|
||||
self.setWindowTitle("About novelWriter")
|
||||
self.setWindowTitle(self.tr("About novelWriter"))
|
||||
self.setMinimumWidth(self.mainConf.pxInt(650))
|
||||
self.setMinimumHeight(self.mainConf.pxInt(600))
|
||||
|
||||
@@ -90,13 +90,14 @@ class GuiAbout(QDialog):
|
||||
|
||||
# Main Tab Area
|
||||
self.tabBox = QTabWidget()
|
||||
self.tabBox.addTab(self.pageAbout, "About")
|
||||
self.tabBox.addTab(self.pageNotes, "Release")
|
||||
self.tabBox.addTab(self.pageLicense, "License")
|
||||
self.tabBox.addTab(self.pageAbout, self.tr("About"))
|
||||
self.tabBox.addTab(self.pageNotes, self.tr("Release"))
|
||||
self.tabBox.addTab(self.pageLicense, self.tr("License"))
|
||||
self.innerBox.addWidget(self.tabBox)
|
||||
|
||||
# OK Button
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("OK"))
|
||||
self.buttonBox.accepted.connect(self._doClose)
|
||||
|
||||
self.outerBox.addLayout(self.innerBox)
|
||||
@@ -132,80 +133,76 @@ class GuiAbout(QDialog):
|
||||
"""Generate the content for the About page.
|
||||
"""
|
||||
listPrefix = " • "
|
||||
aboutMsg = (
|
||||
"<h2>About novelWriter</h2>"
|
||||
"<p>{copyright:s}.</p>"
|
||||
"<p>Website: <a href='{website:s}'>{domain:s}</a></p>"
|
||||
"<p>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.</p>"
|
||||
"<p>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.</p>"
|
||||
"<p>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.</p>"
|
||||
"<p>See the License tab for the full license text, or visit the "
|
||||
"GNU website at "
|
||||
"<a href='https://www.gnu.org/licenses/gpl-3.0.html'>GPL v3.0</a> "
|
||||
"for more details.</p>"
|
||||
"<h3>Credits</h3>"
|
||||
"<p>{credits:s}</p>"
|
||||
webLink = f"<a href='{nw.__url__:s}'>{nw.__domain__:s}</a>"
|
||||
aboutMsg = (
|
||||
"<h2>{title1}</h2>"
|
||||
"<p>{copyright}.</p>"
|
||||
"<p>{website}</p>"
|
||||
"<p>{intro}</p>"
|
||||
"<p>{license1}</p>"
|
||||
"<p>{license2}</p>"
|
||||
"<p>{license3}</p>"
|
||||
"<h3>{title2}</h3>"
|
||||
"<p>{credits}</p>"
|
||||
).format(
|
||||
title1 = self.tr("About novelWriter"),
|
||||
copyright = nw.__copyright__,
|
||||
website = nw.__url__,
|
||||
domain = nw.__domain__,
|
||||
website = self.tr("Website: {0}").format(webLink),
|
||||
title2 = self.tr("Credits"),
|
||||
credits = "<br/>".join(["%s%s" % (listPrefix, x) for x in nw.__credits__]),
|
||||
intro = 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."
|
||||
),
|
||||
license1 = 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."
|
||||
),
|
||||
license2 = 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."
|
||||
),
|
||||
license3 = self.tr(
|
||||
"See the License tab for the full license text, or visit the "
|
||||
"GNU website at {0} for more details."
|
||||
).format(
|
||||
"<a href='https://www.gnu.org/licenses/gpl-3.0.html'>GPL v3.0</a>"
|
||||
),
|
||||
)
|
||||
|
||||
theTheme = self.theParent.theTheme
|
||||
theIcons = self.theParent.theTheme.theIcons
|
||||
if theTheme.themeName:
|
||||
aboutMsg += (
|
||||
"<h4>Theme: {name:s}</h4>"
|
||||
"<p>"
|
||||
"<b>Author:</b> {author:s}<br/>"
|
||||
"<b>Credit:</b> {credit:s}<br/>"
|
||||
"<b>License:</b> <a href='{lic_url:s}'>{license:s}</a>"
|
||||
"</p>"
|
||||
).format(
|
||||
name = theTheme.themeName,
|
||||
author = theTheme.themeAuthor,
|
||||
credit = theTheme.themeCredit,
|
||||
license = theTheme.themeLicense,
|
||||
lic_url = theTheme.themeLicenseUrl,
|
||||
aboutMsg += "<h4>%s</h4><p>%s<br/>%s<br/>%s</p>" % (
|
||||
self.tr("Theme: {0}").format(theTheme.themeName),
|
||||
self.tr("Author: {0}").format(theTheme.themeAuthor),
|
||||
self.tr("Credit: {0}").format(theTheme.themeCredit),
|
||||
self.tr("License: {0}").format(
|
||||
f"<a href='{theTheme.themeLicenseUrl}'>{theTheme.themeLicense}</a>"
|
||||
)
|
||||
)
|
||||
|
||||
if theIcons.themeName:
|
||||
aboutMsg += (
|
||||
"<h4>Icons: {name:s}</h4>"
|
||||
"<p>"
|
||||
"<b>Author:</b> {author:s}<br/>"
|
||||
"<b>Credit:</b> {credit:s}<br/>"
|
||||
"<b>License:</b> <a href='{lic_url:s}'>{license:s}</a>"
|
||||
"</p>"
|
||||
).format(
|
||||
name = theIcons.themeName,
|
||||
author = theIcons.themeAuthor,
|
||||
credit = theIcons.themeCredit,
|
||||
license = theIcons.themeLicense,
|
||||
lic_url = theIcons.themeLicenseUrl,
|
||||
aboutMsg += "<h4>%s</h4><p>%s<br/>%s<br/>%s</p>" % (
|
||||
self.tr("Icons: {0}").format(theIcons.themeName),
|
||||
self.tr("Author: {0}").format(theIcons.themeAuthor),
|
||||
self.tr("Credit: {0}").format(theIcons.themeCredit),
|
||||
self.tr("License: {0}").format(
|
||||
f"<a href='{theIcons.themeLicenseUrl}'>{theIcons.themeLicense}</a>"
|
||||
)
|
||||
)
|
||||
|
||||
if theTheme.syntaxName:
|
||||
aboutMsg += (
|
||||
"<h4>Syntax: {name:s}</h4>"
|
||||
"<p>"
|
||||
"<b>Author:</b> {author:s}<br/>"
|
||||
"<b>Credit:</b> {credit:s}<br/>"
|
||||
"<b>License:</b> <a href='{lic_url:s}'>{license:s}</a>"
|
||||
"</p>"
|
||||
).format(
|
||||
name = theTheme.syntaxName,
|
||||
author = theTheme.syntaxAuthor,
|
||||
credit = theTheme.syntaxCredit,
|
||||
license = theTheme.syntaxLicense,
|
||||
lic_url = theTheme.syntaxLicenseUrl,
|
||||
aboutMsg += "<h4>%s</h4><p>%s<br/>%s<br/>%s</p>" % (
|
||||
self.tr("Syntax: {0}").format(theTheme.syntaxName),
|
||||
self.tr("Author: {0}").format(theTheme.syntaxAuthor),
|
||||
self.tr("Credit: {0}").format(theTheme.syntaxCredit),
|
||||
self.tr("License: {0}").format(
|
||||
f"<a href='{theTheme.syntaxLicenseUrl}'>{theTheme.syntaxLicense}</a>"
|
||||
)
|
||||
)
|
||||
|
||||
self.pageAbout.setHtml(aboutMsg)
|
||||
|
||||
+90
-90
@@ -84,7 +84,7 @@ class GuiBuildNovel(QDialog):
|
||||
self.htmlSize = 0 # Size of the html document
|
||||
self.buildTime = 0 # The timestamp of the last build
|
||||
|
||||
self.setWindowTitle("Build Novel Project")
|
||||
self.setWindowTitle(self.tr("Build Novel Project"))
|
||||
self.setMinimumWidth(self.mainConf.pxInt(700))
|
||||
self.setMinimumHeight(self.mainConf.pxInt(600))
|
||||
|
||||
@@ -101,27 +101,26 @@ class GuiBuildNovel(QDialog):
|
||||
# Title Formats
|
||||
# =============
|
||||
|
||||
self.titleGroup = QGroupBox("Title Formats for Novel Files", self)
|
||||
self.titleGroup = QGroupBox(self.tr("Title Formats for Novel Files"), self)
|
||||
self.titleForm = QGridLayout(self)
|
||||
self.titleGroup.setLayout(self.titleForm)
|
||||
|
||||
fmtHelp = (
|
||||
r"<b>Formatting Codes:</b><br>"
|
||||
r"%title% for the title as set in the document<br>"
|
||||
r"%ch% for chapter number (1, 2, 3)<br>"
|
||||
r"%chw% for chapter number as a word (one, two)<br>"
|
||||
r"%chI% for chapter number in upper case Roman<br>"
|
||||
r"%chi% for chapter number in lower case Roman<br>"
|
||||
r"%sc% for scene number within chapter<br>"
|
||||
r"%sca% for scene number within novel"
|
||||
)
|
||||
fmtScHelp = (
|
||||
r"<br><br>"
|
||||
r"Leave blank to skip this heading, or set to a static text, like "
|
||||
r"for instance '* * *', to make a separator. The separator will "
|
||||
r"be centred automatically and only appear between sections of "
|
||||
r"the same type."
|
||||
)
|
||||
fmtHelp = "<br>".join([
|
||||
"<b>%s</b>" % self.tr("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%"),
|
||||
self.tr("{0} for chapter number as a word (one, two)").format(r"%chw%"),
|
||||
self.tr("{0} for chapter number in upper case Roman").format(r"%chI%"),
|
||||
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 = "<br><br>%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()
|
||||
@@ -176,11 +175,11 @@ class GuiBuildNovel(QDialog):
|
||||
self.boxSection = QHBoxLayout()
|
||||
self.boxSection.addWidget(self.fmtSection)
|
||||
|
||||
titleLabel = QLabel("Title")
|
||||
chapterLabel = QLabel("Chapter")
|
||||
unnumbLabel = QLabel("Unnumbered")
|
||||
sceneLabel = QLabel("Scene")
|
||||
sectionLabel = QLabel("Section")
|
||||
titleLabel = QLabel(self.tr("Title"))
|
||||
chapterLabel = QLabel(self.tr("Chapter"))
|
||||
unnumbLabel = QLabel(self.tr("Unnumbered"))
|
||||
sceneLabel = QLabel(self.tr("Scene"))
|
||||
sectionLabel = QLabel(self.tr("Section"))
|
||||
|
||||
self.titleForm.addWidget(titleLabel, 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.titleForm.addLayout(self.boxTitle, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -199,7 +198,7 @@ class GuiBuildNovel(QDialog):
|
||||
# Font Options
|
||||
# ============
|
||||
|
||||
self.fontGroup = QGroupBox("Font Options", self)
|
||||
self.fontGroup = QGroupBox(self.tr("Font Options"), self)
|
||||
self.fontForm = QGridLayout(self)
|
||||
self.fontGroup.setLayout(self.fontForm)
|
||||
|
||||
@@ -237,11 +236,11 @@ class GuiBuildNovel(QDialog):
|
||||
self.boxFont = QHBoxLayout()
|
||||
self.boxFont.addWidget(self.textFont)
|
||||
|
||||
fontFamilyLabel = QLabel("Font family")
|
||||
fontSizeLabel = QLabel("Font size")
|
||||
lineHeightLabel = QLabel("Line height")
|
||||
justifyLabel = QLabel("Justify text")
|
||||
stylingLabel = QLabel("Disable styling")
|
||||
fontFamilyLabel = QLabel(self.tr("Font family"))
|
||||
fontSizeLabel = QLabel(self.tr("Font size"))
|
||||
lineHeightLabel = QLabel(self.tr("Line height"))
|
||||
justifyLabel = QLabel(self.tr("Justify text"))
|
||||
stylingLabel = QLabel(self.tr("Disable styling"))
|
||||
|
||||
self.fontForm.addWidget(fontFamilyLabel, 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.fontForm.addLayout(self.boxFont, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -283,7 +282,7 @@ class GuiBuildNovel(QDialog):
|
||||
# Include Options
|
||||
# ===============
|
||||
|
||||
self.textGroup = QGroupBox("Include Options", self)
|
||||
self.textGroup = QGroupBox(self.tr("Include Options"), self)
|
||||
self.textForm = QGridLayout(self)
|
||||
self.textGroup.setLayout(self.textForm)
|
||||
|
||||
@@ -307,10 +306,10 @@ class GuiBuildNovel(QDialog):
|
||||
self.optState.getBool("GuiBuildNovel", "incBodyText", True)
|
||||
)
|
||||
|
||||
synopsisLabel = QLabel("Include synopsis")
|
||||
commentsLabel = QLabel("Include comments")
|
||||
keywordsLabel = QLabel("Include keywords")
|
||||
bodyLabel = QLabel("Include body text")
|
||||
synopsisLabel = QLabel(self.tr("Include synopsis"))
|
||||
commentsLabel = QLabel(self.tr("Include comments"))
|
||||
keywordsLabel = QLabel(self.tr("Include keywords"))
|
||||
bodyLabel = QLabel(self.tr("Include body text"))
|
||||
|
||||
self.textForm.addWidget(synopsisLabel, 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.textForm.addWidget(self.includeSynopsis, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -327,37 +326,34 @@ class GuiBuildNovel(QDialog):
|
||||
# File Filter Options
|
||||
# ===================
|
||||
|
||||
self.fileGroup = QGroupBox("File Filter Options", self)
|
||||
self.fileGroup = QGroupBox(self.tr("File Filter Options"), self)
|
||||
self.fileForm = QGridLayout(self)
|
||||
self.fileGroup.setLayout(self.fileForm)
|
||||
|
||||
self.novelFiles = QSwitch(width=wS, height=hS)
|
||||
self.novelFiles.setToolTip(
|
||||
"Include files with layouts 'Book', 'Page', 'Partition', "
|
||||
"'Chapter', 'Unnumbered', and 'Scene'."
|
||||
)
|
||||
self.novelFiles.setToolTip(self.tr("Include files with layouts other than 'Note'."))
|
||||
self.novelFiles.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "addNovel", True)
|
||||
)
|
||||
|
||||
self.noteFiles = QSwitch(width=wS, height=hS)
|
||||
self.noteFiles.setToolTip("Include files with layout 'Note'.")
|
||||
self.noteFiles.setToolTip(self.tr("Include files with layout 'Note'."))
|
||||
self.noteFiles.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "addNotes", False)
|
||||
)
|
||||
|
||||
self.ignoreFlag = QSwitch(width=wS, height=hS)
|
||||
self.ignoreFlag.setToolTip(
|
||||
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)
|
||||
)
|
||||
|
||||
novelLabel = QLabel("Include novel files")
|
||||
notesLabel = QLabel("Include note files")
|
||||
exportLabel = QLabel("Ignore export flag")
|
||||
novelLabel = QLabel(self.tr("Include novel files"))
|
||||
notesLabel = QLabel(self.tr("Include note files"))
|
||||
exportLabel = QLabel(self.tr("Ignore export flag"))
|
||||
|
||||
self.fileForm.addWidget(novelLabel, 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.fileForm.addWidget(self.novelFiles, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -372,7 +368,7 @@ class GuiBuildNovel(QDialog):
|
||||
# Export Options
|
||||
# ==============
|
||||
|
||||
self.exportGroup = QGroupBox("Export Options", self)
|
||||
self.exportGroup = QGroupBox(self.tr("Export Options"), self)
|
||||
self.exportForm = QGridLayout(self)
|
||||
self.exportGroup.setLayout(self.exportForm)
|
||||
|
||||
@@ -386,8 +382,8 @@ class GuiBuildNovel(QDialog):
|
||||
self.optState.getBool("GuiBuildNovel", "replaceUCode", False)
|
||||
)
|
||||
|
||||
tabsLabel = QLabel("Replace tabs with spaces")
|
||||
uCodeLabel = QLabel("Replace Unicode in HTML")
|
||||
tabsLabel = QLabel(self.tr("Replace tabs with spaces"))
|
||||
uCodeLabel = QLabel(self.tr("Replace Unicode in HTML"))
|
||||
|
||||
self.exportForm.addWidget(tabsLabel, 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.exportForm.addWidget(self.replaceTabs, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -402,7 +398,7 @@ class GuiBuildNovel(QDialog):
|
||||
|
||||
self.buildProgress = QProgressBar()
|
||||
|
||||
self.buildNovel = QPushButton("Build Preview")
|
||||
self.buildNovel = QPushButton(self.tr("Build Preview"))
|
||||
self.buildNovel.clicked.connect(self._buildPreview)
|
||||
|
||||
# Action Buttons
|
||||
@@ -413,56 +409,56 @@ class GuiBuildNovel(QDialog):
|
||||
# Printing
|
||||
|
||||
self.printMenu = QMenu(self)
|
||||
self.btnPrint = QPushButton("Print")
|
||||
self.btnPrint = QPushButton(self.tr("Print"))
|
||||
self.btnPrint.setMenu(self.printMenu)
|
||||
|
||||
self.printSend = QAction("Print Preview", self)
|
||||
self.printSend = QAction(self.tr("Print Preview"), self)
|
||||
self.printSend.triggered.connect(self._printDocument)
|
||||
self.printMenu.addAction(self.printSend)
|
||||
|
||||
self.printFile = QAction("Print to PDF", self)
|
||||
self.printFile = QAction(self.tr("Print to PDF"), self)
|
||||
self.printFile.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
|
||||
self.printMenu.addAction(self.printFile)
|
||||
|
||||
# Saving to File
|
||||
|
||||
self.saveMenu = QMenu(self)
|
||||
self.btnSave = QPushButton("Save As")
|
||||
self.btnSave = QPushButton(self.tr("Save As"))
|
||||
self.btnSave.setMenu(self.saveMenu)
|
||||
|
||||
self.saveODT = QAction("Open Document (.odt)", self)
|
||||
self.saveODT = QAction(self.tr("Open Document (.odt)"), self)
|
||||
self.saveODT.triggered.connect(lambda: self._saveDocument(self.FMT_ODT))
|
||||
self.saveMenu.addAction(self.saveODT)
|
||||
|
||||
self.saveFODT = QAction("Flat Open Document (.fodt)", self)
|
||||
self.saveFODT = QAction(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("novelWriter HTML (.htm)", self)
|
||||
self.saveHTM = QAction(self.tr("novelWriter HTML (.htm)"), self)
|
||||
self.saveHTM.triggered.connect(lambda: self._saveDocument(self.FMT_HTM))
|
||||
self.saveMenu.addAction(self.saveHTM)
|
||||
|
||||
self.saveNWD = QAction("novelWriter Markdown (.nwd)", self)
|
||||
self.saveNWD = QAction(self.tr("novelWriter Markdown (.nwd)"), self)
|
||||
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
|
||||
self.saveMenu.addAction(self.saveNWD)
|
||||
|
||||
self.saveMD = QAction("Standard Markdown (.md)", self)
|
||||
self.saveMD = QAction(self.tr("Standard Markdown (.md)"), self)
|
||||
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
|
||||
self.saveMenu.addAction(self.saveMD)
|
||||
|
||||
self.saveGH = QAction("GitHub Markdown (.md)", self)
|
||||
self.saveGH = QAction(self.tr("GitHub Markdown (.md)"), self)
|
||||
self.saveGH.triggered.connect(lambda: self._saveDocument(self.FMT_GH))
|
||||
self.saveMenu.addAction(self.saveGH)
|
||||
|
||||
self.saveJsonH = QAction("JSON + novelWriter HTML (.json)", self)
|
||||
self.saveJsonH = QAction(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("JSON + novelWriters Markdown (.json)", self)
|
||||
self.saveJsonM = QAction(self.tr("JSON + novelWriters Markdown (.json)"), self)
|
||||
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
|
||||
self.saveMenu.addAction(self.saveJsonM)
|
||||
|
||||
self.btnClose = QPushButton("Close")
|
||||
self.btnClose = QPushButton(self.tr("Close"))
|
||||
self.btnClose.clicked.connect(self._doClose)
|
||||
|
||||
self.buttonBox.addWidget(self.btnSave)
|
||||
@@ -567,7 +563,7 @@ class GuiBuildNovel(QDialog):
|
||||
self.docView.setContent(self.htmlText, self.buildTime)
|
||||
else:
|
||||
self.docView.setText(
|
||||
"Failed to generate preview. The result is too big."
|
||||
self.tr("Failed to generate preview. The result is too big.")
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -736,10 +732,10 @@ class GuiBuildNovel(QDialog):
|
||||
logger.debug("Built project in %.3f ms" % (1000*(tEnd - tStart)))
|
||||
|
||||
if bldObj.errData:
|
||||
self.theParent.makeAlert((
|
||||
"There were problems when building the project:"
|
||||
"<br>- %s"
|
||||
) % "<br>- ".join(bldObj.errData), nwAlert.ERROR)
|
||||
self.theParent.makeAlert("%s:<br>- %s" % (
|
||||
self.tr("There were problems when building the project"),
|
||||
"<br>- ".join(bldObj.errData)), nwAlert.ERROR
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@@ -796,39 +792,39 @@ class GuiBuildNovel(QDialog):
|
||||
|
||||
if theFmt == self.FMT_ODT:
|
||||
fileExt = "odt"
|
||||
textFmt = "Open Document"
|
||||
textFmt = self.tr("Open Document")
|
||||
|
||||
elif theFmt == self.FMT_FODT:
|
||||
fileExt = "fodt"
|
||||
textFmt = "Flat Open Document"
|
||||
textFmt = self.tr("Flat Open Document")
|
||||
|
||||
elif theFmt == self.FMT_HTM:
|
||||
fileExt = "htm"
|
||||
textFmt = "Plain HTML"
|
||||
textFmt = self.tr("Plain HTML")
|
||||
|
||||
elif theFmt == self.FMT_NWD:
|
||||
fileExt = "nwd"
|
||||
textFmt = "novelWriter Markdown"
|
||||
textFmt = self.tr("novelWriter Markdown")
|
||||
|
||||
elif theFmt == self.FMT_MD:
|
||||
fileExt = "md"
|
||||
textFmt = "Standard Markdown"
|
||||
textFmt = self.tr("Standard Markdown")
|
||||
|
||||
elif theFmt == self.FMT_GH:
|
||||
fileExt = "md"
|
||||
textFmt = "GitHub Markdown"
|
||||
textFmt = self.tr("GitHub Markdown")
|
||||
|
||||
elif theFmt == self.FMT_JSON_H:
|
||||
fileExt = "json"
|
||||
textFmt = "JSON + novelWriter HTML"
|
||||
textFmt = self.tr("JSON + novelWriter HTML")
|
||||
|
||||
elif theFmt == self.FMT_JSON_M:
|
||||
fileExt = "json"
|
||||
textFmt = "JSON + novelWriter Markdown"
|
||||
textFmt = self.tr("JSON + novelWriter Markdown")
|
||||
|
||||
elif theFmt == self.FMT_PDF:
|
||||
fileExt = "pdf"
|
||||
textFmt = "PDF"
|
||||
textFmt = self.tr("PDF")
|
||||
|
||||
else:
|
||||
return False
|
||||
@@ -848,7 +844,7 @@ class GuiBuildNovel(QDialog):
|
||||
dlgOpt = QFileDialog.Options()
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
savePath, _ = QFileDialog.getSaveFileName(
|
||||
self, "Save Document As", savePath, options=dlgOpt
|
||||
self, self.tr("Save Document As"), savePath, options=dlgOpt
|
||||
)
|
||||
if not savePath:
|
||||
return False
|
||||
@@ -985,20 +981,20 @@ class GuiBuildNovel(QDialog):
|
||||
errMsg - str(e)
|
||||
|
||||
else:
|
||||
errMsg = "Unknown format"
|
||||
errMsg = self.tr("Unknown format")
|
||||
|
||||
# Report to user
|
||||
if wSuccess:
|
||||
self.theParent.makeAlert(
|
||||
"%s file successfully written to:<br> %s" % (
|
||||
textFmt, savePath
|
||||
), nwAlert.INFO
|
||||
"%s<br>%s" % (
|
||||
self.tr("{0} file successfully written to:").format(textFmt), savePath
|
||||
),
|
||||
nwAlert.INFO
|
||||
)
|
||||
else:
|
||||
self.theParent.makeAlert(
|
||||
"Failed to write %s file. %s" % (
|
||||
textFmt, errMsg
|
||||
), nwAlert.ERROR
|
||||
self.tr("Failed to write {0} file. {1}").format(textFmt, errMsg),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
|
||||
return wSuccess
|
||||
@@ -1193,11 +1189,11 @@ class GuiBuildNovelDocView(QTextBrowser):
|
||||
|
||||
self.qDocument = self.document()
|
||||
self.qDocument.setDocumentMargin(self.mainConf.getTextMargin())
|
||||
self.setPlaceholderText(
|
||||
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."
|
||||
)
|
||||
))
|
||||
|
||||
theFont = QFont()
|
||||
if self.mainConf.textFont is None:
|
||||
@@ -1227,7 +1223,7 @@ class GuiBuildNovelDocView(QTextBrowser):
|
||||
|
||||
fPx = int(1.1*self.theTheme.fontPixelSize)
|
||||
|
||||
self.theTitle = QLabel("<b>Build Time:</b> Unknown", self)
|
||||
self.theTitle = QLabel("", self)
|
||||
self.theTitle.setIndent(0)
|
||||
self.theTitle.setAutoFillBackground(True)
|
||||
self.theTitle.setAlignment(Qt.AlignCenter)
|
||||
@@ -1236,6 +1232,7 @@ class GuiBuildNovelDocView(QTextBrowser):
|
||||
self.theTitle.setFont(lblFont)
|
||||
|
||||
self._updateDocMargins()
|
||||
self._updateBuildAge()
|
||||
self.setStyleSheet()
|
||||
|
||||
# Age Timer
|
||||
@@ -1341,8 +1338,11 @@ class GuiBuildNovelDocView(QTextBrowser):
|
||||
fuzzyTime(time() - self.buildTime)
|
||||
)
|
||||
else:
|
||||
strBuildTime = "Unknown"
|
||||
self.theTitle.setText("<b>Build Time:</b> %s" % strBuildTime)
|
||||
strBuildTime = self.tr("Unknown")
|
||||
|
||||
self.theTitle.setText(self.tr("<b>Build Time:</b> {0}").format(strBuildTime))
|
||||
|
||||
return
|
||||
|
||||
def _updateDocMargins(self):
|
||||
"""Automatically adjust the header to fill the top of the
|
||||
|
||||
@@ -500,6 +500,8 @@ class QuotesDialog(QDialog):
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doAccept)
|
||||
self.buttonBox.rejected.connect(self._doReject)
|
||||
|
||||
|
||||
+105
-85
@@ -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,11 +293,17 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
docSize = len(theDoc)
|
||||
if docSize > nwConst.MAX_DOCSIZE:
|
||||
self.theParent.makeAlert((
|
||||
"The document you are trying to open is too big. "
|
||||
"The document size is %.2f\u202fMB. "
|
||||
"The maximum size allowed is %.2f\u202fMB."
|
||||
) % (docSize/1.0e6, nwConst.MAX_DOCSIZE/1.0e6), nwAlert.ERROR)
|
||||
self.theParent.makeAlert(
|
||||
self.tr(
|
||||
"The document you are trying to open is too big. "
|
||||
"The document size is {0} MB. "
|
||||
"The maximum size allowed is {1} MB."
|
||||
).format(
|
||||
f"{docSize/1.0e6:.2f}",
|
||||
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
|
||||
),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
self.clearEditor()
|
||||
return False
|
||||
|
||||
@@ -380,11 +386,17 @@ class GuiDocEditor(QTextEdit):
|
||||
"""
|
||||
docSize = len(theText)
|
||||
if docSize > nwConst.MAX_DOCSIZE:
|
||||
self.theParent.makeAlert((
|
||||
"The text you are trying to add is too big. "
|
||||
"The text size is %.2f\u202fMB. "
|
||||
"The maximum size allowed is %.2f\u202fMB."
|
||||
) % (docSize/1.0e6, nwConst.MAX_DOCSIZE/1.0e6), nwAlert.ERROR)
|
||||
self.theParent.makeAlert(
|
||||
self.tr(
|
||||
"The text you are trying to add is too big. "
|
||||
"The text size is {0} MB. "
|
||||
"The maximum size allowed is {1} MB."
|
||||
).format(
|
||||
f"{docSize/1.0e6:.2f}",
|
||||
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
|
||||
),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
|
||||
@@ -568,12 +580,14 @@ class GuiDocEditor(QTextEdit):
|
||||
"""
|
||||
if not isinstance(theLine, int):
|
||||
return False
|
||||
|
||||
if theLine >= 0:
|
||||
theBlock = self.qDocument.findBlockByLineNumber(theLine)
|
||||
if theBlock:
|
||||
self.setCursorPosition(theBlock.position())
|
||||
self.docFooter.updateLineCount()
|
||||
logger.verbose("Cursor moved to line %d" % theLine)
|
||||
|
||||
return True
|
||||
|
||||
##
|
||||
@@ -591,11 +605,9 @@ class GuiDocEditor(QTextEdit):
|
||||
theLang = self.theProject.projLang
|
||||
|
||||
self.theDict.setLanguage(theLang, self.theProject.projDict)
|
||||
theTag, theProvider = self.theDict.describeDict()
|
||||
|
||||
aLang, aName = self.theDict.describeDict()
|
||||
self.theParent.statusBar.setLanguage(
|
||||
aLang, "%s [%s]" % (self.mainConf.spellTool.title(), aName.title())
|
||||
)
|
||||
self.theParent.statusBar.setLanguage(theLang, theProvider)
|
||||
|
||||
if not self.bigDoc:
|
||||
self.spellCheckDocument()
|
||||
@@ -641,10 +653,8 @@ class GuiDocEditor(QTextEdit):
|
||||
self.hLight.rehighlight()
|
||||
qApp.restoreOverrideCursor()
|
||||
afTime = time()
|
||||
logger.debug(
|
||||
"Document highlighted in %.3f ms" % (1000*(afTime-bfTime))
|
||||
)
|
||||
self.theParent.statusBar.showMessage("Spell check complete")
|
||||
logger.debug("Document highlighted in %.3f ms" % (1000*(afTime-bfTime)))
|
||||
self.theParent.statusBar.showMessage(self.tr("Spell check complete"))
|
||||
|
||||
return True
|
||||
|
||||
@@ -743,14 +753,14 @@ class GuiDocEditor(QTextEdit):
|
||||
return False
|
||||
|
||||
msgBox = QMessageBox()
|
||||
msgBox.information(self, "File Location", (
|
||||
"File details for the currently open file<br>"
|
||||
"Handle: {handle:s}<br>"
|
||||
"Location: {fileLoc:s}"
|
||||
).format(
|
||||
handle = self.theHandle,
|
||||
fileLoc = str(self.nwDocument.getFileLocation())
|
||||
))
|
||||
msgBox.information(
|
||||
self,
|
||||
self.tr("File Location"),
|
||||
"%s<br>%s" % (
|
||||
self.tr("The currently open file is saved in:"),
|
||||
self.nwDocument.getFileLocation()
|
||||
),
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@@ -799,7 +809,7 @@ class GuiDocEditor(QTextEdit):
|
||||
theCursor = self.textCursor()
|
||||
theBlock = theCursor.block()
|
||||
if not theBlock.isValid():
|
||||
logger.error("Filed to insert keyword '%s'" % keyWord)
|
||||
logger.error("Failed to insert keyword '%s'" % keyWord)
|
||||
return False
|
||||
|
||||
theCursor.beginEditBlock()
|
||||
@@ -933,10 +943,15 @@ class GuiDocEditor(QTextEdit):
|
||||
self.lastFind = None
|
||||
|
||||
if self.qDocument.characterCount() > nwConst.MAX_DOCSIZE:
|
||||
self.theParent.makeAlert((
|
||||
"The document has grown too big and you cannot add more text to it. "
|
||||
"The maximum size of a single novelWriter document is %.2f\u202fMB."
|
||||
) % (nwConst.MAX_DOCSIZE/1.0e6), 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 {0} MB."
|
||||
).format(
|
||||
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
|
||||
),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
self.undo()
|
||||
return
|
||||
|
||||
@@ -966,21 +981,21 @@ class GuiDocEditor(QTextEdit):
|
||||
# ===========================
|
||||
|
||||
if self._followTag(theCursor=posCursor, loadTag=False):
|
||||
mnuTag = QAction("Follow Tag", mnuContext)
|
||||
mnuTag = QAction(self.tr("Follow Tag"), mnuContext)
|
||||
mnuTag.triggered.connect(lambda: self._followTag(theCursor=posCursor))
|
||||
mnuContext.addAction(mnuTag)
|
||||
mnuContext.addSeparator()
|
||||
|
||||
if userSelection:
|
||||
mnuCut = QAction("Cut", mnuContext)
|
||||
mnuCut = QAction(self.tr("Cut"), mnuContext)
|
||||
mnuCut.triggered.connect(lambda: self.docAction(nwDocAction.CUT))
|
||||
mnuContext.addAction(mnuCut)
|
||||
|
||||
mnuCopy = QAction("Copy", mnuContext)
|
||||
mnuCopy = QAction(self.tr("Copy"), mnuContext)
|
||||
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
||||
mnuContext.addAction(mnuCopy)
|
||||
|
||||
mnuPaste = QAction("Paste", mnuContext)
|
||||
mnuPaste = QAction(self.tr("Paste"), mnuContext)
|
||||
mnuPaste.triggered.connect(lambda: self.docAction(nwDocAction.PASTE))
|
||||
mnuContext.addAction(mnuPaste)
|
||||
|
||||
@@ -989,17 +1004,17 @@ class GuiDocEditor(QTextEdit):
|
||||
# Selections
|
||||
# ==========
|
||||
|
||||
mnuSelAll = QAction("Select All", mnuContext)
|
||||
mnuSelAll = QAction(self.tr("Select All"), mnuContext)
|
||||
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
||||
mnuContext.addAction(mnuSelAll)
|
||||
|
||||
mnuSelWord = QAction("Select Word", mnuContext)
|
||||
mnuSelWord = QAction(self.tr("Select Word"), mnuContext)
|
||||
mnuSelWord.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.WordUnderCursor, thePos)
|
||||
)
|
||||
mnuContext.addAction(mnuSelWord)
|
||||
|
||||
mnuSelPara = QAction("Select Paragraph", mnuContext)
|
||||
mnuSelPara = QAction(self.tr("Select Paragraph"), mnuContext)
|
||||
mnuSelPara.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.BlockUnderCursor, thePos)
|
||||
)
|
||||
@@ -1025,7 +1040,7 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
if spellCheck:
|
||||
mnuContext.addSeparator()
|
||||
mnuHead = QAction("Spelling Suggestion(s)", mnuContext)
|
||||
mnuHead = QAction(self.tr("Spelling Suggestion(s)"), mnuContext)
|
||||
mnuContext.addAction(mnuHead)
|
||||
|
||||
theSuggest = self.theDict.suggestWords(theWord)[:15]
|
||||
@@ -1037,11 +1052,13 @@ class GuiDocEditor(QTextEdit):
|
||||
)
|
||||
mnuContext.addAction(mnuWord)
|
||||
else:
|
||||
mnuHead = QAction("%s No Suggestions" % nwUnicode.U_ENDASH, mnuContext)
|
||||
mnuHead = QAction(
|
||||
"%s %s" % (nwUnicode.U_ENDASH, self.tr("No Suggestions")), mnuContext
|
||||
)
|
||||
mnuContext.addAction(mnuHead)
|
||||
|
||||
mnuContext.addSeparator()
|
||||
mnuAdd = QAction("Add Word to Dictionary", mnuContext)
|
||||
mnuAdd = QAction(self.tr("Add Word to Dictionary"), mnuContext)
|
||||
mnuAdd.triggered.connect(lambda thePos: self._addWord(posCursor))
|
||||
mnuContext.addAction(mnuAdd)
|
||||
|
||||
@@ -1131,15 +1148,11 @@ class GuiDocEditor(QTextEdit):
|
||||
QPointF(theSize.width(), theSize.height()), Qt.FuzzyHit
|
||||
)
|
||||
if self.queuePos <= thePos:
|
||||
logger.verbose(
|
||||
"Allowed cursor move to %d <= %d" % (self.queuePos, thePos)
|
||||
)
|
||||
logger.verbose("Allowed cursor move to %d <= %d" % (self.queuePos, thePos))
|
||||
self.setCursorPosition(self.queuePos)
|
||||
self.queuePos = None
|
||||
else:
|
||||
logger.verbose(
|
||||
"Denied cursor move to %d > %d" % (self.queuePos, thePos)
|
||||
)
|
||||
logger.verbose("Denied cursor move to %d > %d" % (self.queuePos, thePos))
|
||||
return
|
||||
|
||||
##
|
||||
@@ -1317,7 +1330,8 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
else:
|
||||
self.theParent.makeAlert(
|
||||
"Please selection some text before calling replace quotes.", nwAlert.ERROR
|
||||
self.tr("Please selection some text before calling replace quotes."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
|
||||
return
|
||||
@@ -1530,9 +1544,7 @@ class GuiDocEditor(QTextEdit):
|
||||
theText = newText
|
||||
cOffset -= 0
|
||||
else:
|
||||
logger.error(
|
||||
"Unknown or unsupported block format requested: %s" % str(docAction)
|
||||
)
|
||||
logger.error("Unknown or unsupported block format requested: %s" % str(docAction))
|
||||
return False
|
||||
|
||||
# Replace the block text
|
||||
@@ -1817,12 +1829,12 @@ class GuiDocEditSearch(QFrame):
|
||||
# ==========
|
||||
self.searchBox = QLineEdit(self)
|
||||
self.searchBox.setFont(boxFont)
|
||||
self.searchBox.setPlaceholderText("Search")
|
||||
self.searchBox.setPlaceholderText(self.tr("Search"))
|
||||
self.searchBox.returnPressed.connect(self._doSearch)
|
||||
|
||||
self.replaceBox = QLineEdit(self)
|
||||
self.replaceBox.setFont(boxFont)
|
||||
self.replaceBox.setPlaceholderText("Replace")
|
||||
self.replaceBox.setPlaceholderText(self.tr("Replace"))
|
||||
self.replaceBox.returnPressed.connect(self._doReplace)
|
||||
|
||||
self.searchOpt = QToolBar(self)
|
||||
@@ -1831,44 +1843,44 @@ class GuiDocEditSearch(QFrame):
|
||||
self.searchOpt.setContentsMargins(0, 0, 0, 0)
|
||||
self.searchOpt.setStyleSheet(r"QToolBar {padding: 0;}")
|
||||
|
||||
self.searchLabel = QLabel("Search")
|
||||
self.searchLabel = QLabel(self.tr("Search"))
|
||||
self.searchLabel.setFont(boxFont)
|
||||
self.searchLabel.setIndent(self.mainConf.pxInt(6))
|
||||
|
||||
self.toggleCase = QAction("Case Sensitive", self)
|
||||
self.toggleCase.setToolTip("Match case")
|
||||
self.toggleCase = QAction(self.tr("Case Sensitive"), self)
|
||||
self.toggleCase.setToolTip(self.tr("Match case"))
|
||||
self.toggleCase.setIcon(self.theTheme.getIcon("search_case"))
|
||||
self.toggleCase.setCheckable(True)
|
||||
self.toggleCase.setChecked(self.isCaseSense)
|
||||
self.toggleCase.toggled.connect(self._doToggleCase)
|
||||
self.searchOpt.addAction(self.toggleCase)
|
||||
|
||||
self.toggleWord = QAction("Whole Words Only", self)
|
||||
self.toggleWord.setToolTip("Match whole words")
|
||||
self.toggleWord = QAction(self.tr("Whole Words Only"), self)
|
||||
self.toggleWord.setToolTip(self.tr("Match whole words"))
|
||||
self.toggleWord.setIcon(self.theTheme.getIcon("search_word"))
|
||||
self.toggleWord.setCheckable(True)
|
||||
self.toggleWord.setChecked(self.isWholeWord)
|
||||
self.toggleWord.toggled.connect(self._doToggleWord)
|
||||
self.searchOpt.addAction(self.toggleWord)
|
||||
|
||||
self.toggleRegEx = QAction("RegEx Mode", self)
|
||||
self.toggleRegEx.setToolTip("Use regular expressions (requires Qt 5.3)")
|
||||
self.toggleRegEx = QAction(self.tr("RegEx Mode"), self)
|
||||
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)
|
||||
self.toggleRegEx.toggled.connect(self._doToggleRegEx)
|
||||
self.searchOpt.addAction(self.toggleRegEx)
|
||||
|
||||
self.toggleLoop = QAction("Loop Search", self)
|
||||
self.toggleLoop.setToolTip("Loop the search when reaching the end")
|
||||
self.toggleLoop = QAction(self.tr("Loop Search"), self)
|
||||
self.toggleLoop.setToolTip(self.tr("Loop the search when reaching the end"))
|
||||
self.toggleLoop.setIcon(self.theTheme.getIcon("search_loop"))
|
||||
self.toggleLoop.setCheckable(True)
|
||||
self.toggleLoop.setChecked(self.doLoop)
|
||||
self.toggleLoop.toggled.connect(self._doToggleLoop)
|
||||
self.searchOpt.addAction(self.toggleLoop)
|
||||
|
||||
self.toggleProject = QAction("Search Next File", self)
|
||||
self.toggleProject.setToolTip("Continue searching in the next file")
|
||||
self.toggleProject = QAction(self.tr("Search Next File"), self)
|
||||
self.toggleProject.setToolTip(self.tr("Continue searching in the next file"))
|
||||
self.toggleProject.setIcon(self.theTheme.getIcon("search_project"))
|
||||
self.toggleProject.setCheckable(True)
|
||||
self.toggleProject.setChecked(self.doNextFile)
|
||||
@@ -1877,8 +1889,8 @@ class GuiDocEditSearch(QFrame):
|
||||
|
||||
self.searchOpt.addSeparator()
|
||||
|
||||
self.toggleMatchCap = QAction("Preserve Case", self)
|
||||
self.toggleMatchCap.setToolTip("Preserve case on replace")
|
||||
self.toggleMatchCap = QAction(self.tr("Preserve Case"), self)
|
||||
self.toggleMatchCap.setToolTip(self.tr("Preserve case on replace"))
|
||||
self.toggleMatchCap.setIcon(self.theTheme.getIcon("search_preserve"))
|
||||
self.toggleMatchCap.setCheckable(True)
|
||||
self.toggleMatchCap.setChecked(self.doMatchCap)
|
||||
@@ -1887,8 +1899,8 @@ class GuiDocEditSearch(QFrame):
|
||||
|
||||
self.searchOpt.addSeparator()
|
||||
|
||||
self.cancelSearch = QAction("Close Search", self)
|
||||
self.cancelSearch.setToolTip("Close the search box [Esc]")
|
||||
self.cancelSearch = QAction(self.tr("Close Search"), self)
|
||||
self.cancelSearch.setToolTip(self.tr("Close the search box [{0}]").format("Esc"))
|
||||
self.cancelSearch.setIcon(self.theTheme.getIcon("search_cancel"))
|
||||
self.cancelSearch.triggered.connect(self._doClose)
|
||||
self.searchOpt.addAction(self.cancelSearch)
|
||||
@@ -1900,18 +1912,18 @@ class GuiDocEditSearch(QFrame):
|
||||
self.showReplace = QToolButton(self)
|
||||
self.showReplace.setArrowType(Qt.RightArrow)
|
||||
self.showReplace.setCheckable(True)
|
||||
self.showReplace.setToolTip("Show/hide the replace text box")
|
||||
self.showReplace.setToolTip(self.tr("Show/hide the replace text box"))
|
||||
self.showReplace.setStyleSheet(r"QToolButton {border: none; background: transparent;}")
|
||||
self.showReplace.toggled.connect(self._doToggleReplace)
|
||||
|
||||
self.searchButton = QPushButton(self.theTheme.getIcon("search"), "")
|
||||
self.searchButton.setFixedSize(QSize(bPx, bPx))
|
||||
self.searchButton.setToolTip("Find in current document")
|
||||
self.searchButton.setToolTip(self.tr("Find in current document"))
|
||||
self.searchButton.clicked.connect(self._doSearch)
|
||||
|
||||
self.replaceButton = QPushButton(self.theTheme.getIcon("search-replace"), "")
|
||||
self.replaceButton.setFixedSize(QSize(bPx, bPx))
|
||||
self.replaceButton.setToolTip("Find and replace in current document")
|
||||
self.replaceButton.setToolTip(self.tr("Find and replace in current document"))
|
||||
self.replaceButton.clicked.connect(self._doReplace)
|
||||
|
||||
self.mainBox.addWidget(self.searchLabel, 0, 0, 1, 2, Qt.AlignLeft)
|
||||
@@ -2204,7 +2216,7 @@ class GuiDocEditHeader(QWidget):
|
||||
self.editButton.setStyleSheet(buttonStyle)
|
||||
self.editButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.editButton.setVisible(False)
|
||||
self.editButton.setToolTip("Edit document meta")
|
||||
self.editButton.setToolTip(self.tr("Edit document meta"))
|
||||
self.editButton.clicked.connect(self._editDocument)
|
||||
|
||||
self.searchButton = QToolButton(self)
|
||||
@@ -2215,7 +2227,7 @@ class GuiDocEditHeader(QWidget):
|
||||
self.searchButton.setStyleSheet(buttonStyle)
|
||||
self.searchButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.searchButton.setVisible(False)
|
||||
self.searchButton.setToolTip("Search document")
|
||||
self.searchButton.setToolTip(self.tr("Search document"))
|
||||
self.searchButton.clicked.connect(self._searchDocument)
|
||||
|
||||
self.minmaxButton = QToolButton(self)
|
||||
@@ -2226,7 +2238,7 @@ class GuiDocEditHeader(QWidget):
|
||||
self.minmaxButton.setStyleSheet(buttonStyle)
|
||||
self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.minmaxButton.setVisible(False)
|
||||
self.minmaxButton.setToolTip("Toggle Focus Mode")
|
||||
self.minmaxButton.setToolTip(self.tr("Toggle Focus Mode"))
|
||||
self.minmaxButton.clicked.connect(self._minmaxDocument)
|
||||
|
||||
self.closeButton = QToolButton(self)
|
||||
@@ -2237,7 +2249,7 @@ class GuiDocEditHeader(QWidget):
|
||||
self.closeButton.setStyleSheet(buttonStyle)
|
||||
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.closeButton.setVisible(False)
|
||||
self.closeButton.setToolTip("Close the document")
|
||||
self.closeButton.setToolTip(self.tr("Close the document"))
|
||||
self.closeButton.clicked.connect(self._closeDocument)
|
||||
|
||||
# Assemble Layout
|
||||
@@ -2413,7 +2425,7 @@ class GuiDocEditFooter(QWidget):
|
||||
self.statusIcon.setFixedHeight(self.sPx)
|
||||
self.statusIcon.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.statusText = QLabel("Status")
|
||||
self.statusText = QLabel(self.tr("Status"))
|
||||
self.statusText.setIndent(0)
|
||||
self.statusText.setMargin(0)
|
||||
self.statusText.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -2429,7 +2441,7 @@ class GuiDocEditFooter(QWidget):
|
||||
self.linesIcon.setFixedHeight(self.sPx)
|
||||
self.linesIcon.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.linesText = QLabel("Line: 0")
|
||||
self.linesText = QLabel("")
|
||||
self.linesText.setIndent(0)
|
||||
self.linesText.setMargin(0)
|
||||
self.linesText.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -2445,7 +2457,7 @@ class GuiDocEditFooter(QWidget):
|
||||
self.wordsIcon.setFixedHeight(self.sPx)
|
||||
self.wordsIcon.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.wordsText = QLabel("Words: 0")
|
||||
self.wordsText = QLabel("")
|
||||
self.wordsText.setIndent(0)
|
||||
self.wordsText.setMargin(0)
|
||||
self.wordsText.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -2476,6 +2488,8 @@ class GuiDocEditFooter(QWidget):
|
||||
|
||||
# Fix the Colours
|
||||
self.matchColours()
|
||||
self.updateLineCount()
|
||||
self.updateCounts()
|
||||
|
||||
logger.debug("GuiDocEditFooter initialisation complete")
|
||||
|
||||
@@ -2532,8 +2546,8 @@ class GuiDocEditFooter(QWidget):
|
||||
theIcon = self.theParent.importIcons[iStatus]
|
||||
|
||||
sIcon = theIcon.pixmap(self.sPx, self.sPx)
|
||||
sClass = nwLabels.CLASS_NAME[self.theItem.itemClass]
|
||||
sLayout = 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)
|
||||
@@ -2552,7 +2566,9 @@ class GuiDocEditFooter(QWidget):
|
||||
iLine = theCursor.blockNumber() + 1
|
||||
iDist = 100*iLine/self.docEditor.qDocument.blockCount()
|
||||
|
||||
self.linesText.setText(f"Line: {iLine:n} ({iDist:.0f}\u202f%)")
|
||||
self.linesText.setText(
|
||||
self.tr("Line: {0} ({1})").format(f"{iLine:n}", f"{iDist:.0f} %")
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@@ -2566,10 +2582,14 @@ class GuiDocEditFooter(QWidget):
|
||||
wCount = self.theItem.wordCount
|
||||
wDiff = wCount - self.theItem.initCount
|
||||
|
||||
self.wordsText.setText(f"Words: {wCount:n} ({wDiff:+n})")
|
||||
self.wordsText.setText(
|
||||
self.tr("Words: {0} ({1})").format(f"{wCount:n}", f"{wDiff:+n}")
|
||||
)
|
||||
|
||||
byteSize = self.docEditor.qDocument.characterCount()
|
||||
self.wordsText.setToolTip(f"Document size is {byteSize:n} bytes")
|
||||
self.wordsText.setToolTip(
|
||||
self.tr("Document size is {0} bytes").format(f"{byteSize:n}")
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+17
-15
@@ -53,11 +53,11 @@ class GuiDocMerge(QDialog):
|
||||
self.sourceItem = None
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.setWindowTitle("Merge Documents")
|
||||
self.setWindowTitle(self.tr("Merge Documents"))
|
||||
|
||||
self.headLabel = QLabel("<b>Documents to Merge</b>")
|
||||
self.headLabel = QLabel("<b>%s</b>" % self.tr("Documents to Merge"))
|
||||
self.helpLabel = QHelpLabel(
|
||||
"Drag and drop items to change the order.", self.theParent.theTheme.helpText
|
||||
self.tr("Drag and drop items to change the order."), self.theParent.theTheme.helpText
|
||||
)
|
||||
|
||||
self.listBox = QListWidget()
|
||||
@@ -66,6 +66,8 @@ class GuiDocMerge(QDialog):
|
||||
self.listBox.setMinimumHeight(self.mainConf.pxInt(180))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doMerge)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
@@ -102,9 +104,9 @@ class GuiDocMerge(QDialog):
|
||||
finalOrder.append(self.listBox.item(i).data(Qt.UserRole))
|
||||
|
||||
if len(finalOrder) == 0:
|
||||
self.theParent.makeAlert((
|
||||
"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)
|
||||
@@ -114,16 +116,16 @@ class GuiDocMerge(QDialog):
|
||||
theText += "\n\n"
|
||||
|
||||
if self.sourceItem is None:
|
||||
self.theParent.makeAlert((
|
||||
"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((
|
||||
"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)
|
||||
@@ -164,9 +166,9 @@ class GuiDocMerge(QDialog):
|
||||
if nwItem is None:
|
||||
return
|
||||
if nwItem.itemType is not nwItemType.FOLDER:
|
||||
self.theParent.makeAlert((
|
||||
"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):
|
||||
|
||||
+40
-29
@@ -56,11 +56,12 @@ class GuiDocSplit(QDialog):
|
||||
self.sourceItem = None
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.setWindowTitle("Split Document")
|
||||
self.setWindowTitle(self.tr("Split Document"))
|
||||
|
||||
self.headLabel = QLabel("<b>Document Headers</b>")
|
||||
self.headLabel = QLabel("<b>%s</b>" % self.tr("Document Headers"))
|
||||
self.helpLabel = QHelpLabel(
|
||||
"Select the maximum level to split into files.", self.theParent.theTheme.helpText
|
||||
self.tr("Select the maximum level to split into files."),
|
||||
self.theParent.theTheme.helpText
|
||||
)
|
||||
|
||||
self.listBox = QListWidget()
|
||||
@@ -69,10 +70,10 @@ class GuiDocSplit(QDialog):
|
||||
self.listBox.setMinimumHeight(self.mainConf.pxInt(180))
|
||||
|
||||
self.splitLevel = QComboBox(self)
|
||||
self.splitLevel.addItem("Split on Header Level 1 (Title)", 1)
|
||||
self.splitLevel.addItem("Split up to Header Level 2 (Chapter)", 2)
|
||||
self.splitLevel.addItem("Split up to Header Level 3 (Scene)", 3)
|
||||
self.splitLevel.addItem("Split up to Header Level 4 (Section)", 4)
|
||||
self.splitLevel.addItem(self.tr("Split on Header Level 1 (Title)"), 1)
|
||||
self.splitLevel.addItem(self.tr("Split up to Header Level 2 (Chapter)"), 2)
|
||||
self.splitLevel.addItem(self.tr("Split up to Header Level 3 (Scene)"), 3)
|
||||
self.splitLevel.addItem(self.tr("Split up to Header Level 4 (Section)"), 4)
|
||||
spIndex = self.splitLevel.findData(
|
||||
self.optState.getInt("GuiDocSplit", "spLevel", 3)
|
||||
)
|
||||
@@ -81,6 +82,8 @@ class GuiDocSplit(QDialog):
|
||||
self.splitLevel.currentIndexChanged.connect(self._populateList)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doSplit)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
@@ -115,16 +118,16 @@ class GuiDocSplit(QDialog):
|
||||
logger.verbose("GuiDocSplit split button clicked")
|
||||
|
||||
if self.sourceItem is None:
|
||||
self.theParent.makeAlert((
|
||||
"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((
|
||||
"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)
|
||||
@@ -147,26 +150,34 @@ class GuiDocSplit(QDialog):
|
||||
|
||||
nFiles = len(finalOrder)
|
||||
if nFiles == 0:
|
||||
self.theParent.makeAlert((
|
||||
"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((
|
||||
"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("Split Document", (
|
||||
"The document will be split into %d file(s) in a new folder. "
|
||||
"The original document will remain intact.<br><br>"
|
||||
"Continue with the splitting process?"
|
||||
) % nFiles)
|
||||
msgYes = self.theParent.askQuestion(
|
||||
self.tr("Split Document"),
|
||||
"%s<br><br>%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
|
||||
|
||||
@@ -242,9 +253,9 @@ class GuiDocSplit(QDialog):
|
||||
if nwItem is None:
|
||||
return
|
||||
if nwItem.itemType is not nwItemType.FILE:
|
||||
self.theParent.makeAlert((
|
||||
"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()
|
||||
|
||||
+26
-23
@@ -183,7 +183,7 @@ class GuiDocViewer(QTextBrowser):
|
||||
except Exception:
|
||||
logger.error("Failed to generate preview for document with handle '%s'" % tHandle)
|
||||
nw.logException()
|
||||
self.setText("An error occurred while generating the preview.")
|
||||
self.setText(self.tr("An error occurred while generating the preview."))
|
||||
return False
|
||||
|
||||
# Refresh the tab stops
|
||||
@@ -243,11 +243,14 @@ class GuiDocViewer(QTextBrowser):
|
||||
logger.debug("Loading document from tag '%s'" % theTag)
|
||||
tHandle, _, sTitle = self.theParent.theIndex.getTagSource(theTag)
|
||||
if tHandle is None:
|
||||
self.theParent.makeAlert((
|
||||
"Could not find the reference for tag '%s'. It either doesn't "
|
||||
"exist, or the index is out of date. The index can be updated "
|
||||
"from the Tools menu, or by pressing F9."
|
||||
) % theTag, nwAlert.ERROR)
|
||||
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
|
||||
)
|
||||
return False
|
||||
else:
|
||||
# Let the parent handle the opening as it also ensures that
|
||||
@@ -415,7 +418,7 @@ class GuiDocViewer(QTextBrowser):
|
||||
# ===================
|
||||
|
||||
if userSelection:
|
||||
mnuCopy = QAction("Copy", mnuContext)
|
||||
mnuCopy = QAction(self.tr("Copy"), mnuContext)
|
||||
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
||||
mnuContext.addAction(mnuCopy)
|
||||
|
||||
@@ -424,17 +427,17 @@ class GuiDocViewer(QTextBrowser):
|
||||
# Selections
|
||||
# ==========
|
||||
|
||||
mnuSelAll = QAction("Select All", mnuContext)
|
||||
mnuSelAll = QAction(self.tr("Select All"), mnuContext)
|
||||
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
||||
mnuContext.addAction(mnuSelAll)
|
||||
|
||||
mnuSelWord = QAction("Select Word", mnuContext)
|
||||
mnuSelWord = QAction(self.tr("Select Word"), mnuContext)
|
||||
mnuSelWord.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.WordUnderCursor, thePos)
|
||||
)
|
||||
mnuContext.addAction(mnuSelWord)
|
||||
|
||||
mnuSelPara = QAction("Select Paragraph", mnuContext)
|
||||
mnuSelPara = QAction(self.tr("Select Paragraph"), mnuContext)
|
||||
mnuSelPara.triggered.connect(
|
||||
lambda: self._makePosSelection(QTextCursor.BlockUnderCursor, thePos)
|
||||
)
|
||||
@@ -740,7 +743,7 @@ class GuiDocViewHeader(QWidget):
|
||||
self.backButton.setStyleSheet(buttonStyle)
|
||||
self.backButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.backButton.setVisible(False)
|
||||
self.backButton.setToolTip("Go backward")
|
||||
self.backButton.setToolTip(self.tr("Go backward"))
|
||||
self.backButton.clicked.connect(self.docViewer.navBackward)
|
||||
|
||||
self.forwardButton = QToolButton(self)
|
||||
@@ -751,7 +754,7 @@ class GuiDocViewHeader(QWidget):
|
||||
self.forwardButton.setStyleSheet(buttonStyle)
|
||||
self.forwardButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.forwardButton.setVisible(False)
|
||||
self.forwardButton.setToolTip("Go forward")
|
||||
self.forwardButton.setToolTip(self.tr("Go forward"))
|
||||
self.forwardButton.clicked.connect(self.docViewer.navForward)
|
||||
|
||||
self.refreshButton = QToolButton(self)
|
||||
@@ -762,7 +765,7 @@ class GuiDocViewHeader(QWidget):
|
||||
self.refreshButton.setStyleSheet(buttonStyle)
|
||||
self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.refreshButton.setVisible(False)
|
||||
self.refreshButton.setToolTip("Reload the document")
|
||||
self.refreshButton.setToolTip(self.tr("Reload the document"))
|
||||
self.refreshButton.clicked.connect(self._refreshDocument)
|
||||
|
||||
self.closeButton = QToolButton(self)
|
||||
@@ -773,7 +776,7 @@ class GuiDocViewHeader(QWidget):
|
||||
self.closeButton.setStyleSheet(buttonStyle)
|
||||
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||
self.closeButton.setVisible(False)
|
||||
self.closeButton.setToolTip("Close the document")
|
||||
self.closeButton.setToolTip(self.tr("Close the document"))
|
||||
self.closeButton.clicked.connect(self._closeDocument)
|
||||
|
||||
# Assemble Layout
|
||||
@@ -944,7 +947,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showHide.setIconSize(QSize(fPx, fPx))
|
||||
self.showHide.setFixedSize(QSize(fPx, fPx))
|
||||
self.showHide.clicked.connect(self._doShowHide)
|
||||
self.showHide.setToolTip("Show/hide the references panel")
|
||||
self.showHide.setToolTip(self.tr("Show/hide the references panel"))
|
||||
|
||||
# Sticky Button
|
||||
self.stickyRefs = QToolButton(self)
|
||||
@@ -955,9 +958,9 @@ class GuiDocViewFooter(QWidget):
|
||||
self.stickyRefs.setIconSize(QSize(fPx, fPx))
|
||||
self.stickyRefs.setFixedSize(QSize(fPx, fPx))
|
||||
self.stickyRefs.toggled.connect(self._doToggleSticky)
|
||||
self.stickyRefs.setToolTip(
|
||||
self.stickyRefs.setToolTip(self.tr(
|
||||
"Activate to freeze the content of the references panel when changing document"
|
||||
)
|
||||
))
|
||||
|
||||
# Show Comments
|
||||
self.showComments = QToolButton(self)
|
||||
@@ -969,7 +972,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showComments.setIconSize(QSize(fPx, fPx))
|
||||
self.showComments.setFixedSize(QSize(fPx, fPx))
|
||||
self.showComments.toggled.connect(self._doToggleComments)
|
||||
self.showComments.setToolTip("Show comments")
|
||||
self.showComments.setToolTip(self.tr("Show comments"))
|
||||
|
||||
# Show Synopsis
|
||||
self.showSynopsis = QToolButton(self)
|
||||
@@ -981,10 +984,10 @@ class GuiDocViewFooter(QWidget):
|
||||
self.showSynopsis.setIconSize(QSize(fPx, fPx))
|
||||
self.showSynopsis.setFixedSize(QSize(fPx, fPx))
|
||||
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
||||
self.showSynopsis.setToolTip("Show synopsis comments")
|
||||
self.showSynopsis.setToolTip(self.tr("Show synopsis comments"))
|
||||
|
||||
# Labels
|
||||
self.lblRefs = QLabel("References")
|
||||
self.lblRefs = QLabel(self.tr("References"))
|
||||
self.lblRefs.setBuddy(self.showHide)
|
||||
self.lblRefs.setIndent(0)
|
||||
self.lblRefs.setMargin(0)
|
||||
@@ -993,7 +996,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.lblRefs.setFixedHeight(fPx)
|
||||
self.lblRefs.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.lblSticky = QLabel("Sticky")
|
||||
self.lblSticky = QLabel(self.tr("Sticky"))
|
||||
self.lblSticky.setBuddy(self.stickyRefs)
|
||||
self.lblSticky.setIndent(0)
|
||||
self.lblSticky.setMargin(0)
|
||||
@@ -1002,7 +1005,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.lblSticky.setFixedHeight(fPx)
|
||||
self.lblSticky.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.lblComments = QLabel("Comments")
|
||||
self.lblComments = QLabel(self.tr("Comments"))
|
||||
self.lblComments.setBuddy(self.showComments)
|
||||
self.lblComments.setIndent(0)
|
||||
self.lblComments.setMargin(0)
|
||||
@@ -1011,7 +1014,7 @@ class GuiDocViewFooter(QWidget):
|
||||
self.lblComments.setFixedHeight(fPx)
|
||||
self.lblComments.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
|
||||
self.lblSynopsis = QLabel("Synopsis")
|
||||
self.lblSynopsis = QLabel(self.tr("Synopsis"))
|
||||
self.lblSynopsis.setBuddy(self.showSynopsis)
|
||||
self.lblSynopsis.setIndent(0)
|
||||
self.lblSynopsis.setMargin(0)
|
||||
|
||||
+12
-12
@@ -32,7 +32,7 @@ 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__)
|
||||
@@ -67,7 +67,7 @@ class GuiItemDetails(QWidget):
|
||||
self.fntValue.setPointSizeF(0.9*fPt)
|
||||
|
||||
# Label
|
||||
self.labelName = QLabel("Label")
|
||||
self.labelName = QLabel(self.tr("Label"))
|
||||
self.labelName.setFont(self.fntLabel)
|
||||
self.labelName.setAlignment(Qt.AlignLeft | Qt.AlignBaseline)
|
||||
|
||||
@@ -80,7 +80,7 @@ class GuiItemDetails(QWidget):
|
||||
self.labelData.setWordWrap(True)
|
||||
|
||||
# Status
|
||||
self.statusName = QLabel("Status")
|
||||
self.statusName = QLabel(self.tr("Status"))
|
||||
self.statusName.setFont(self.fntLabel)
|
||||
self.statusName.setAlignment(Qt.AlignLeft)
|
||||
|
||||
@@ -92,7 +92,7 @@ class GuiItemDetails(QWidget):
|
||||
self.statusData.setAlignment(Qt.AlignLeft)
|
||||
|
||||
# Class
|
||||
self.className = QLabel("Class")
|
||||
self.className = QLabel(self.tr("Class"))
|
||||
self.className.setFont(self.fntLabel)
|
||||
self.className.setAlignment(Qt.AlignLeft)
|
||||
|
||||
@@ -105,7 +105,7 @@ class GuiItemDetails(QWidget):
|
||||
self.classData.setAlignment(Qt.AlignLeft)
|
||||
|
||||
# Layout
|
||||
self.layoutName = QLabel("Layout")
|
||||
self.layoutName = QLabel(self.tr("Layout"))
|
||||
self.layoutName.setFont(self.fntLabel)
|
||||
self.layoutName.setAlignment(Qt.AlignLeft)
|
||||
|
||||
@@ -118,7 +118,7 @@ class GuiItemDetails(QWidget):
|
||||
self.layoutData.setAlignment(Qt.AlignLeft)
|
||||
|
||||
# Character Count
|
||||
self.cCountName = QLabel(" 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(" 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(" Paragraphs")
|
||||
self.pCountName = QLabel(" "+self.tr("Paragraphs"))
|
||||
self.pCountName.setFont(self.fntLabel)
|
||||
self.pCountName.setAlignment(Qt.AlignRight)
|
||||
|
||||
@@ -259,17 +259,17 @@ class GuiItemDetails(QWidget):
|
||||
|
||||
iPx = int(round(0.8*self.theTheme.baseIconSize))
|
||||
self.statusFlag.setPixmap(flagIcon.pixmap(iPx, iPx))
|
||||
self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass])
|
||||
self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass]) # NO-I18N
|
||||
|
||||
if nwItem.itemLayout == nwItemLayout.NO_LAYOUT:
|
||||
self.layoutFlag.setText("-")
|
||||
else:
|
||||
self.layoutFlag.setText(nwLabels.LAYOUT_FLAG[nwItem.itemLayout])
|
||||
self.layoutFlag.setText(nwLabels.LAYOUT_FLAG[nwItem.itemLayout]) # NO-I18N
|
||||
|
||||
self.labelData.setText(theLabel)
|
||||
self.statusData.setText(nwItem.itemStatus)
|
||||
self.classData.setText(nwLabels.CLASS_NAME[nwItem.itemClass])
|
||||
self.layoutData.setText(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}")
|
||||
|
||||
+18
-12
@@ -34,7 +34,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
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__)
|
||||
|
||||
@@ -58,7 +58,7 @@ class GuiItemEditor(QDialog):
|
||||
if self.theItem is None:
|
||||
self._doClose()
|
||||
|
||||
self.setWindowTitle("Item Settings")
|
||||
self.setWindowTitle(self.tr("Item Settings"))
|
||||
|
||||
mVd = self.mainConf.pxInt(220)
|
||||
mSp = self.mainConf.pxInt(16)
|
||||
@@ -103,10 +103,10 @@ class GuiItemEditor(QDialog):
|
||||
|
||||
for itemLayout in nwItemLayout:
|
||||
if itemLayout in validLayouts:
|
||||
self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout], itemLayout)
|
||||
self.editLayout.addItem(trConst(nwLabels.LAYOUT_NAME[itemLayout]), itemLayout)
|
||||
|
||||
# Export Switch
|
||||
self.textExport = QLabel("Include when building project")
|
||||
self.textExport = QLabel(self.tr("Include when building project"))
|
||||
self.editExport = QSwitch()
|
||||
if self.theItem.itemType == nwItemType.FILE:
|
||||
self.editExport.setEnabled(True)
|
||||
@@ -117,6 +117,8 @@ class GuiItemEditor(QDialog):
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
@@ -136,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("Label"), 0, 0, 1, 1)
|
||||
self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
|
||||
self.mainForm.addWidget(QLabel("Status"), 1, 0, 1, 1)
|
||||
self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
|
||||
self.mainForm.addWidget(QLabel("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)
|
||||
|
||||
+251
-227
File diff suppressed because it is too large
Load Diff
+8
-4
@@ -63,7 +63,11 @@ class GuiNovelTree(QTreeWidget):
|
||||
self.setIconSize(QSize(iPx, iPx))
|
||||
self.setIndentation(iPx)
|
||||
self.setColumnCount(3)
|
||||
self.setHeaderLabels(["Title", "Words", "POV"])
|
||||
self.setHeaderLabels([
|
||||
self.tr("Title"),
|
||||
self.tr("Words"),
|
||||
self.tr("POV")
|
||||
])
|
||||
self.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||
self.itemSelectionChanged.connect(self._itemSelected)
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
@@ -73,9 +77,9 @@ class GuiNovelTree(QTreeWidget):
|
||||
|
||||
treeHeadItem = self.headerItem()
|
||||
treeHeadItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
|
||||
treeHeadItem.setToolTip(self.C_TITLE, "Section title")
|
||||
treeHeadItem.setToolTip(self.C_WORDS, "Word count")
|
||||
treeHeadItem.setToolTip(self.C_POV, "Point-of-view character")
|
||||
treeHeadItem.setToolTip(self.C_TITLE, self.tr("Section title"))
|
||||
treeHeadItem.setToolTip(self.C_WORDS, self.tr("Word count"))
|
||||
treeHeadItem.setToolTip(self.C_POV, self.tr("Point-of-view character"))
|
||||
|
||||
treeHeader = self.header()
|
||||
treeHeader.setStretchLastSection(True)
|
||||
|
||||
+5
-5
@@ -34,7 +34,7 @@ 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,7 +149,7 @@ class GuiOutline(QTreeWidget):
|
||||
"""
|
||||
self.clear()
|
||||
self.setColumnCount(1)
|
||||
self.setHeaderLabel(nwLabels.OUTLINE_COLS[nwOutline.TITLE])
|
||||
self.setHeaderLabel(trConst(nwLabels.OUTLINE_COLS[nwOutline.TITLE]))
|
||||
|
||||
self.treeOrder = []
|
||||
self.colWidth = {}
|
||||
@@ -355,7 +355,7 @@ class GuiOutline(QTreeWidget):
|
||||
if self.firstView:
|
||||
theLabels = []
|
||||
for i, hItem in enumerate(self.treeOrder):
|
||||
theLabels.append(nwLabels.OUTLINE_COLS[hItem])
|
||||
theLabels.append(trConst(nwLabels.OUTLINE_COLS[hItem]))
|
||||
self.colIndex[hItem] = i
|
||||
|
||||
self.setHeaderLabels(theLabels)
|
||||
@@ -474,7 +474,7 @@ class GuiOutlineHeaderMenu(QMenu):
|
||||
self.theParent = theParent
|
||||
self.acceptToggle = True
|
||||
|
||||
mnuHead = QAction("Select Columns", self)
|
||||
mnuHead = QAction(self.tr("Select Columns"), self)
|
||||
self.addAction(mnuHead)
|
||||
self.addSeparator()
|
||||
|
||||
@@ -482,7 +482,7 @@ class GuiOutlineHeaderMenu(QMenu):
|
||||
for hItem in nwOutline:
|
||||
if hItem == nwOutline.TITLE:
|
||||
continue
|
||||
self.actionMap[hItem] = QAction(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)
|
||||
|
||||
+27
-27
@@ -27,12 +27,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import nw
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QT_TRANSLATE_NOOP
|
||||
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 +40,10 @@ logger = logging.getLogger(__name__)
|
||||
class GuiOutlineDetails(QScrollArea):
|
||||
|
||||
LVL_MAP = {
|
||||
"H1" : "Title",
|
||||
"H2" : "Chapter",
|
||||
"H3" : "Scene",
|
||||
"H4" : "Section"
|
||||
"H1" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Title"),
|
||||
"H2" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Chapter"),
|
||||
"H3" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Scene"),
|
||||
"H4" : QT_TRANSLATE_NOOP("GuiOutlineDetails", "Section"),
|
||||
}
|
||||
|
||||
def __init__(self, theParent):
|
||||
@@ -66,9 +66,9 @@ class GuiOutlineDetails(QScrollArea):
|
||||
vSpace = int(self.mainConf.pxInt(4))
|
||||
|
||||
# Details Area
|
||||
self.titleLabel = QLabel("<b>Title</b>")
|
||||
self.fileLabel = QLabel("<b>Document</b>")
|
||||
self.itemLabel = QLabel("<b>Status</b>")
|
||||
self.titleLabel = QLabel("<b>%s</b>" % self.tr("Title"))
|
||||
self.fileLabel = QLabel("<b>%s</b>" % self.tr("Document"))
|
||||
self.itemLabel = QLabel("<b>%s</b>" % self.tr("Status"))
|
||||
self.titleValue = QLabel("")
|
||||
self.fileValue = QLabel("")
|
||||
self.itemValue = QLabel("")
|
||||
@@ -81,9 +81,9 @@ class GuiOutlineDetails(QScrollArea):
|
||||
self.itemValue.setMaximumWidth(maxTitle)
|
||||
|
||||
# Stats Area
|
||||
self.cCLabel = QLabel("<b>Characters</b>")
|
||||
self.wCLabel = QLabel("<b>Words</b>")
|
||||
self.pCLabel = QLabel("<b>Paragraphs</b>")
|
||||
self.cCLabel = QLabel("<b>%s</b>" % self.tr("Characters"))
|
||||
self.wCLabel = QLabel("<b>%s</b>" % self.tr("Words"))
|
||||
self.pCLabel = QLabel("<b>%s</b>" % self.tr("Paragraphs"))
|
||||
self.cCValue = QLabel("")
|
||||
self.wCValue = QLabel("")
|
||||
self.pCValue = QLabel("")
|
||||
@@ -96,7 +96,7 @@ class GuiOutlineDetails(QScrollArea):
|
||||
self.pCValue.setAlignment(Qt.AlignRight)
|
||||
|
||||
# Synopsis
|
||||
self.synopLabel = QLabel("<b>Synopsis</b>")
|
||||
self.synopLabel = QLabel("<b>%s</b>" % self.tr("Synopsis"))
|
||||
self.synopValue = QLabel("")
|
||||
self.synopLWrap = QHBoxLayout()
|
||||
self.synopValue.setWordWrap(True)
|
||||
@@ -104,15 +104,15 @@ class GuiOutlineDetails(QScrollArea):
|
||||
self.synopLWrap.addWidget(self.synopValue, 1)
|
||||
|
||||
# Tags
|
||||
self.povKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.POV_KEY])
|
||||
self.focKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY])
|
||||
self.chrKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY])
|
||||
self.pltKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY])
|
||||
self.timKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.TIME_KEY])
|
||||
self.wldKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY])
|
||||
self.objKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY])
|
||||
self.entKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY])
|
||||
self.cstKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY])
|
||||
self.povKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
|
||||
self.focKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
|
||||
self.chrKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
|
||||
self.pltKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
|
||||
self.timKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
|
||||
self.wldKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
|
||||
self.objKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
|
||||
self.entKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
|
||||
self.cstKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
|
||||
|
||||
self.povKeyLWrap = QHBoxLayout()
|
||||
self.focKeyLWrap = QHBoxLayout()
|
||||
@@ -165,7 +165,7 @@ class GuiOutlineDetails(QScrollArea):
|
||||
self.cstKeyLWrap.addWidget(self.cstKeyValue, 1)
|
||||
|
||||
# Selected Item Details
|
||||
self.mainGroup = QGroupBox("Title Details", self)
|
||||
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
||||
self.mainForm = QGridLayout()
|
||||
self.mainGroup.setLayout(self.mainForm)
|
||||
|
||||
@@ -190,7 +190,7 @@ class GuiOutlineDetails(QScrollArea):
|
||||
self.mainForm.setVerticalSpacing(vSpace)
|
||||
|
||||
# Selected Item Tags
|
||||
self.tagsGroup = QGroupBox("Reference Tags", self)
|
||||
self.tagsGroup = QGroupBox(self.tr("Reference Tags"), self)
|
||||
self.tagsForm = QGridLayout()
|
||||
self.tagsGroup.setLayout(self.tagsForm)
|
||||
|
||||
@@ -256,7 +256,7 @@ class GuiOutlineDetails(QScrollArea):
|
||||
def clearDetails(self):
|
||||
"""Clear all the data labels.
|
||||
"""
|
||||
self.titleLabel.setText("<b>Title</b>")
|
||||
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
||||
self.titleValue.setText("")
|
||||
self.fileValue.setText("")
|
||||
self.itemValue.setText("")
|
||||
@@ -286,9 +286,9 @@ class GuiOutlineDetails(QScrollArea):
|
||||
return False
|
||||
|
||||
if novIdx["level"] in self.LVL_MAP:
|
||||
self.titleLabel.setText("<b>%s</b>" % self.LVL_MAP[novIdx["level"]])
|
||||
self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP[novIdx["level"]]))
|
||||
else:
|
||||
self.titleLabel.setText("<b>Title</b>")
|
||||
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
||||
self.titleValue.setText(novIdx["title"])
|
||||
|
||||
self.fileValue.setText(nwItem.itemName)
|
||||
|
||||
+151
-139
@@ -28,7 +28,7 @@ import nw
|
||||
import logging
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QLocale
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QWidget, QComboBox, QSpinBox, QPushButton, QDialogButtonBox,
|
||||
@@ -53,7 +53,7 @@ class GuiPreferences(PagedDialog):
|
||||
self.theParent = theParent
|
||||
self.theProject = theProject
|
||||
|
||||
self.setWindowTitle("Preferences")
|
||||
self.setWindowTitle(self.tr("Preferences"))
|
||||
|
||||
self.tabGeneral = GuiPreferencesGeneral(self.theParent)
|
||||
self.tabProjects = GuiPreferencesProjects(self.theParent)
|
||||
@@ -62,14 +62,16 @@ class GuiPreferences(PagedDialog):
|
||||
self.tabSyntax = GuiPreferencesSyntax(self.theParent)
|
||||
self.tabAuto = GuiPreferencesAutomation(self.theParent)
|
||||
|
||||
self.addTab(self.tabGeneral, "General")
|
||||
self.addTab(self.tabProjects, "Projects")
|
||||
self.addTab(self.tabDocs, "Documents")
|
||||
self.addTab(self.tabEditor, "Editor")
|
||||
self.addTab(self.tabSyntax, "Highlighting")
|
||||
self.addTab(self.tabAuto, "Automation")
|
||||
self.addTab(self.tabGeneral, self.tr("General"))
|
||||
self.addTab(self.tabProjects, self.tr("Projects"))
|
||||
self.addTab(self.tabDocs, self.tr("Documents"))
|
||||
self.addTab(self.tabEditor, self.tr("Editor"))
|
||||
self.addTab(self.tabSyntax, self.tr("Highlighting"))
|
||||
self.addTab(self.tabAuto, self.tr("Automation"))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.addControls(self.buttonBox)
|
||||
@@ -98,7 +100,7 @@ class GuiPreferences(PagedDialog):
|
||||
|
||||
if needsRestart:
|
||||
self.theParent.makeAlert(
|
||||
"Some changes will not be applied until novelWriter has been restarted.",
|
||||
self.tr("Some changes will not be applied until novelWriter has been restarted."),
|
||||
nwAlert.INFO
|
||||
)
|
||||
|
||||
@@ -130,7 +132,7 @@ class GuiPreferencesGeneral(QWidget):
|
||||
|
||||
# Look and Feel
|
||||
# =============
|
||||
self.mainForm.addGroupLabel("Look and Feel")
|
||||
self.mainForm.addGroupLabel(self.tr("Look and Feel"))
|
||||
|
||||
## Select Theme
|
||||
self.guiTheme = QComboBox()
|
||||
@@ -143,9 +145,9 @@ class GuiPreferencesGeneral(QWidget):
|
||||
self.guiTheme.setCurrentIndex(themeIdx)
|
||||
|
||||
self.mainForm.addRow(
|
||||
"Main GUI theme",
|
||||
self.tr("Main GUI theme"),
|
||||
self.guiTheme,
|
||||
"Changing this requires restarting novelWriter."
|
||||
self.tr("Changing this requires restarting novelWriter.")
|
||||
)
|
||||
|
||||
## Select Icon Theme
|
||||
@@ -159,18 +161,18 @@ class GuiPreferencesGeneral(QWidget):
|
||||
self.guiIcons.setCurrentIndex(iconIdx)
|
||||
|
||||
self.mainForm.addRow(
|
||||
"Main icon theme",
|
||||
self.tr("Main icon theme"),
|
||||
self.guiIcons,
|
||||
"Changing this requires restarting novelWriter."
|
||||
self.tr("Changing this requires restarting novelWriter.")
|
||||
)
|
||||
|
||||
## Dark Icons
|
||||
self.guiDark = QSwitch()
|
||||
self.guiDark.setChecked(self.mainConf.guiDark)
|
||||
self.mainForm.addRow(
|
||||
"Prefer icons for dark backgrounds",
|
||||
self.tr("Prefer icons for dark backgrounds"),
|
||||
self.guiDark,
|
||||
"May improve the look of icons on dark themes."
|
||||
self.tr("May improve the look of icons on dark themes.")
|
||||
)
|
||||
|
||||
## Font Family
|
||||
@@ -182,9 +184,9 @@ class GuiPreferencesGeneral(QWidget):
|
||||
self.fontButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("...")))
|
||||
self.fontButton.clicked.connect(self._selectFont)
|
||||
self.mainForm.addRow(
|
||||
"Font family",
|
||||
self.tr("Font family"),
|
||||
self.guiFont,
|
||||
"Changing this requires restarting novelWriter.",
|
||||
self.tr("Changing this requires restarting novelWriter."),
|
||||
theButton = self.fontButton
|
||||
)
|
||||
|
||||
@@ -195,38 +197,38 @@ class GuiPreferencesGeneral(QWidget):
|
||||
self.guiFontSize.setSingleStep(1)
|
||||
self.guiFontSize.setValue(self.mainConf.guiFontSize)
|
||||
self.mainForm.addRow(
|
||||
"Font size",
|
||||
self.tr("Font size"),
|
||||
self.guiFontSize,
|
||||
"Changing this requires restarting novelWriter.",
|
||||
theUnit = "pt"
|
||||
self.tr("Changing this requires restarting novelWriter."),
|
||||
theUnit = self.tr("pt")
|
||||
)
|
||||
|
||||
# GUI Settings
|
||||
# ============
|
||||
self.mainForm.addGroupLabel("GUI Settings")
|
||||
self.mainForm.addGroupLabel(self.tr("GUI Settings"))
|
||||
|
||||
self.showFullPath = QSwitch()
|
||||
self.showFullPath.setChecked(self.mainConf.showFullPath)
|
||||
self.mainForm.addRow(
|
||||
"Show full path in document header",
|
||||
self.tr("Show full path in document header"),
|
||||
self.showFullPath,
|
||||
"Add the parent folder names to the header."
|
||||
self.tr("Add the parent folder names to the header.")
|
||||
)
|
||||
|
||||
self.hideVScroll = QSwitch()
|
||||
self.hideVScroll.setChecked(self.mainConf.hideVScroll)
|
||||
self.mainForm.addRow(
|
||||
"Hide vertical scroll bars in main windows",
|
||||
self.tr("Hide vertical scroll bars in main windows"),
|
||||
self.hideVScroll,
|
||||
"Scrolling available with mouse wheel and keys only."
|
||||
self.tr("Scrolling available with mouse wheel and keys only.")
|
||||
)
|
||||
|
||||
self.hideHScroll = QSwitch()
|
||||
self.hideHScroll.setChecked(self.mainConf.hideHScroll)
|
||||
self.mainForm.addRow(
|
||||
"Hide horizontal scroll bars in main windows",
|
||||
self.tr("Hide horizontal scroll bars in main windows"),
|
||||
self.hideHScroll,
|
||||
"Scrolling available with mouse wheel and keys only."
|
||||
self.tr("Scrolling available with mouse wheel and keys only.")
|
||||
)
|
||||
|
||||
return
|
||||
@@ -295,7 +297,7 @@ class GuiPreferencesProjects(QWidget):
|
||||
|
||||
# Automatic Save
|
||||
# ==============
|
||||
self.mainForm.addGroupLabel("Automatic Save")
|
||||
self.mainForm.addGroupLabel(self.tr("Automatic Save"))
|
||||
|
||||
## Document Save Timer
|
||||
self.autoSaveDoc = QSpinBox(self)
|
||||
@@ -304,10 +306,10 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.autoSaveDoc.setSingleStep(1)
|
||||
self.autoSaveDoc.setValue(self.mainConf.autoSaveDoc)
|
||||
self.mainForm.addRow(
|
||||
"Save document interval",
|
||||
self.tr("Save document interval"),
|
||||
self.autoSaveDoc,
|
||||
"How often the open document is automatically saved.",
|
||||
theUnit="seconds"
|
||||
self.tr("How often the open document is automatically saved."),
|
||||
theUnit=self.tr("seconds")
|
||||
)
|
||||
|
||||
## Project Save Timer
|
||||
@@ -317,24 +319,24 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.autoSaveProj.setSingleStep(1)
|
||||
self.autoSaveProj.setValue(self.mainConf.autoSaveProj)
|
||||
self.mainForm.addRow(
|
||||
"Save project interval",
|
||||
self.tr("Save project interval"),
|
||||
self.autoSaveProj,
|
||||
"How often the open project is automatically saved.",
|
||||
theUnit="seconds"
|
||||
self.tr("How often the open project is automatically saved."),
|
||||
theUnit=self.tr("seconds")
|
||||
)
|
||||
|
||||
# Project Backup
|
||||
# ==============
|
||||
self.mainForm.addGroupLabel("Project Backup")
|
||||
self.mainForm.addGroupLabel(self.tr("Project Backup"))
|
||||
|
||||
## Backup Path
|
||||
self.backupPath = self.mainConf.backupPath
|
||||
self.backupGetPath = QPushButton("Browse")
|
||||
self.backupGetPath = QPushButton(self.tr("Browse"))
|
||||
self.backupGetPath.clicked.connect(self._backupFolder)
|
||||
self.backupPathRow = self.mainForm.addRow(
|
||||
"Backup storage location",
|
||||
self.tr("Backup storage location"),
|
||||
self.backupGetPath,
|
||||
"Path: %s" % self.backupPath
|
||||
self.tr("Path: {0}").format(self.backupPath)
|
||||
)
|
||||
|
||||
## Run when closing
|
||||
@@ -342,9 +344,9 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.backupOnClose.setChecked(self.mainConf.backupOnClose)
|
||||
self.backupOnClose.toggled.connect(self._toggledBackupOnClose)
|
||||
self.mainForm.addRow(
|
||||
"Run backup when the project is closed",
|
||||
self.tr("Run backup when the project is closed"),
|
||||
self.backupOnClose,
|
||||
"Can be overridden for individual projects in project settings."
|
||||
self.tr("Can be overridden for individual projects in project settings.")
|
||||
)
|
||||
|
||||
## Ask before backup
|
||||
@@ -353,22 +355,22 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.askBeforeBackup.setChecked(self.mainConf.askBeforeBackup)
|
||||
self.askBeforeBackup.setEnabled(self.mainConf.backupOnClose)
|
||||
self.mainForm.addRow(
|
||||
"Ask before running backup",
|
||||
self.tr("Ask before running backup"),
|
||||
self.askBeforeBackup,
|
||||
"If off, backups will run in the background."
|
||||
self.tr("If off, backups will run in the background.")
|
||||
)
|
||||
|
||||
# Session Timer
|
||||
# =============
|
||||
self.mainForm.addGroupLabel("Session Timer")
|
||||
self.mainForm.addGroupLabel(self.tr("Session Timer"))
|
||||
|
||||
## Pause when idle
|
||||
self.stopWhenIdle = QSwitch()
|
||||
self.stopWhenIdle.setChecked(self.mainConf.stopWhenIdle)
|
||||
self.mainForm.addRow(
|
||||
"Pause the session timer when not writing",
|
||||
self.tr("Pause the session timer when not writing"),
|
||||
self.stopWhenIdle,
|
||||
"Also pauses when the application window does not have focus."
|
||||
self.tr("Also pauses when the application window does not have focus.")
|
||||
)
|
||||
|
||||
## Inactive time for idle
|
||||
@@ -379,10 +381,10 @@ class GuiPreferencesProjects(QWidget):
|
||||
self.userIdleTime.setDecimals(1)
|
||||
self.userIdleTime.setValue(self.mainConf.userIdleTime/60.0)
|
||||
self.mainForm.addRow(
|
||||
"Editor inactive time before pausing timer",
|
||||
self.tr("Editor inactive time before pausing timer"),
|
||||
self.userIdleTime,
|
||||
"User activity includes typing and changing the content.",
|
||||
theUnit="minutes"
|
||||
self.tr("User activity includes typing and changing the content."),
|
||||
theUnit=self.tr("minutes")
|
||||
)
|
||||
|
||||
return
|
||||
@@ -422,11 +424,13 @@ class GuiPreferencesProjects(QWidget):
|
||||
dlgOpt |= QFileDialog.ShowDirsOnly
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
newDir = QFileDialog.getExistingDirectory(
|
||||
self, "Backup Directory", currDir, options=dlgOpt
|
||||
self, self.tr("Backup Directory"), currDir, options=dlgOpt
|
||||
)
|
||||
if newDir:
|
||||
self.backupPath = newDir
|
||||
self.mainForm.setHelpText(self.backupPathRow, "Path: %s" % self.backupPath)
|
||||
self.mainForm.setHelpText(
|
||||
self.backupPathRow, self.tr("Path: {0}").format(self.backupPath)
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -456,7 +460,7 @@ class GuiPreferencesDocuments(QWidget):
|
||||
|
||||
# Text Style
|
||||
# ==========
|
||||
self.mainForm.addGroupLabel("Text Style")
|
||||
self.mainForm.addGroupLabel(self.tr("Text Style"))
|
||||
|
||||
## Font Family
|
||||
self.textFont = QLineEdit()
|
||||
@@ -467,9 +471,9 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.fontButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("...")))
|
||||
self.fontButton.clicked.connect(self._selectFont)
|
||||
self.mainForm.addRow(
|
||||
"Font family",
|
||||
self.tr("Font family"),
|
||||
self.textFont,
|
||||
"Font for the document editor and viewer.",
|
||||
self.tr("Font for the document editor and viewer."),
|
||||
theButton = self.fontButton
|
||||
)
|
||||
|
||||
@@ -480,15 +484,15 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.textSize.setSingleStep(1)
|
||||
self.textSize.setValue(self.mainConf.textSize)
|
||||
self.mainForm.addRow(
|
||||
"Font size",
|
||||
self.tr("Font size"),
|
||||
self.textSize,
|
||||
"Font size for the document editor and viewer.",
|
||||
theUnit = "pt"
|
||||
self.tr("Font size for the document editor and viewer."),
|
||||
theUnit = self.tr("pt")
|
||||
)
|
||||
|
||||
# Text Flow
|
||||
# =========
|
||||
self.mainForm.addGroupLabel("Text Flow")
|
||||
self.mainForm.addGroupLabel(self.tr("Text Flow"))
|
||||
|
||||
## Max Text Width in Normal Mode
|
||||
self.textWidth = QSpinBox(self)
|
||||
@@ -497,10 +501,10 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.textWidth.setSingleStep(10)
|
||||
self.textWidth.setValue(self.mainConf.textWidth)
|
||||
self.mainForm.addRow(
|
||||
"Maximum text width in \"Normal Mode\"",
|
||||
self.tr("Maximum text width in \"Normal Mode\""),
|
||||
self.textWidth,
|
||||
"Horizontal margins are scaled automatically.",
|
||||
theUnit="px"
|
||||
self.tr("Horizontal margins are scaled automatically."),
|
||||
theUnit=self.tr("px")
|
||||
)
|
||||
|
||||
## Max Text Width in Focus Mode
|
||||
@@ -510,37 +514,37 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.focusWidth.setSingleStep(10)
|
||||
self.focusWidth.setValue(self.mainConf.focusWidth)
|
||||
self.mainForm.addRow(
|
||||
"Maximum text width in \"Focus Mode\"",
|
||||
self.tr("Maximum text width in \"Focus Mode\""),
|
||||
self.focusWidth,
|
||||
"Horizontal margins are scaled automatically.",
|
||||
theUnit="px"
|
||||
self.tr("Horizontal margins are scaled automatically."),
|
||||
theUnit=self.tr("px")
|
||||
)
|
||||
|
||||
## Document Fixed Width
|
||||
self.textFixedW = QSwitch()
|
||||
self.textFixedW.setChecked(not self.mainConf.textFixedW)
|
||||
self.mainForm.addRow(
|
||||
"Disable maximum text width in \"Normal Mode\"",
|
||||
self.tr("Disable maximum text width in \"Normal Mode\""),
|
||||
self.textFixedW,
|
||||
"Text width is defined by the margins only."
|
||||
self.tr("Text width is defined by the margins only.")
|
||||
)
|
||||
|
||||
## Focus Mode Footer
|
||||
self.hideFocusFooter = QSwitch()
|
||||
self.hideFocusFooter.setChecked(self.mainConf.hideFocusFooter)
|
||||
self.mainForm.addRow(
|
||||
"Hide document footer in \"Focus Mode\"",
|
||||
self.tr("Hide document footer in \"Focus Mode\""),
|
||||
self.hideFocusFooter,
|
||||
"Hide the information bar at the bottom of the document."
|
||||
self.tr("Hide the information bar at the bottom of the document.")
|
||||
)
|
||||
|
||||
## Justify Text
|
||||
self.doJustify = QSwitch()
|
||||
self.doJustify.setChecked(self.mainConf.doJustify)
|
||||
self.mainForm.addRow(
|
||||
"Justify the text margins in editor and viewer",
|
||||
self.tr("Justify the text margins in editor and viewer"),
|
||||
self.doJustify,
|
||||
"Lay out text with straight edges in the editor and viewer."
|
||||
self.tr("Lay out text with straight edges in the editor and viewer.")
|
||||
)
|
||||
|
||||
## Document Margins
|
||||
@@ -550,10 +554,10 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.textMargin.setSingleStep(1)
|
||||
self.textMargin.setValue(self.mainConf.textMargin)
|
||||
self.mainForm.addRow(
|
||||
"Text margin",
|
||||
self.tr("Text margin"),
|
||||
self.textMargin,
|
||||
"If maximum width is set, this becomes the minimum margin.",
|
||||
theUnit="px"
|
||||
self.tr("If maximum width is set, this becomes the minimum margin."),
|
||||
theUnit=self.tr("px")
|
||||
)
|
||||
|
||||
## Tab Width
|
||||
@@ -563,10 +567,10 @@ class GuiPreferencesDocuments(QWidget):
|
||||
self.tabWidth.setSingleStep(1)
|
||||
self.tabWidth.setValue(self.mainConf.tabWidth)
|
||||
self.mainForm.addRow(
|
||||
"Tab width",
|
||||
self.tr("Tab width"),
|
||||
self.tabWidth,
|
||||
"The width of a tab key press in the editor and viewer.",
|
||||
theUnit="px"
|
||||
self.tr("The width of a tab key press in the editor and viewer."),
|
||||
theUnit=self.tr("px")
|
||||
)
|
||||
|
||||
return
|
||||
@@ -624,14 +628,19 @@ class GuiPreferencesEditor(QWidget):
|
||||
self.mainForm.setHelpTextStyle(self.theTheme.helpText)
|
||||
self.setLayout(self.mainForm)
|
||||
|
||||
mW = self.mainConf.pxInt(250)
|
||||
|
||||
# Spell Checking
|
||||
# ==============
|
||||
self.mainForm.addGroupLabel("Spell Checking")
|
||||
self.mainForm.addGroupLabel(self.tr("Spell Checking"))
|
||||
|
||||
## Spell Check Provider and Language
|
||||
self.spellLangList = QComboBox(self)
|
||||
self.spellLangList.setMaximumWidth(mW)
|
||||
|
||||
self.spellToolList = QComboBox(self)
|
||||
self.spellToolList.addItem("Internal (difflib)", nwConst.SP_INTERNAL)
|
||||
self.spellToolList.setMaximumWidth(mW)
|
||||
self.spellToolList.addItem("%s (difflib)" % self.tr("Internal"), nwConst.SP_INTERNAL)
|
||||
self.spellToolList.addItem("Spell Enchant (pyenchant)", nwConst.SP_ENCHANT)
|
||||
|
||||
theModel = self.spellToolList.model()
|
||||
@@ -645,14 +654,14 @@ class GuiPreferencesEditor(QWidget):
|
||||
self._doUpdateSpellTool(0)
|
||||
|
||||
self.mainForm.addRow(
|
||||
"Spell check provider",
|
||||
self.tr("Spell check provider"),
|
||||
self.spellToolList,
|
||||
"Note that the internal spell check tool is quite slow."
|
||||
self.tr("Note that the internal spell check tool is quite slow.")
|
||||
)
|
||||
self.mainForm.addRow(
|
||||
"Spell check language",
|
||||
self.tr("Spell check language"),
|
||||
self.spellLangList,
|
||||
"Available languages are determined by your system."
|
||||
self.tr("Available languages are determined by your system.")
|
||||
)
|
||||
|
||||
## Big Document Size Limit
|
||||
@@ -662,15 +671,15 @@ class GuiPreferencesEditor(QWidget):
|
||||
self.bigDocLimit.setSingleStep(10)
|
||||
self.bigDocLimit.setValue(self.mainConf.bigDocLimit)
|
||||
self.mainForm.addRow(
|
||||
"Big document limit",
|
||||
self.tr("Big document limit"),
|
||||
self.bigDocLimit,
|
||||
"Full spell checking is disabled above this limit.",
|
||||
theUnit="kB"
|
||||
self.tr("Full spell checking is disabled above this limit."),
|
||||
theUnit=self.tr("kB")
|
||||
)
|
||||
|
||||
# Word Count
|
||||
# ==========
|
||||
self.mainForm.addGroupLabel("Word Count")
|
||||
self.mainForm.addGroupLabel(self.tr("Word Count"))
|
||||
|
||||
## Word Count Timer
|
||||
self.wordCountTimer = QDoubleSpinBox(self)
|
||||
@@ -680,54 +689,54 @@ class GuiPreferencesEditor(QWidget):
|
||||
self.wordCountTimer.setSingleStep(0.1)
|
||||
self.wordCountTimer.setValue(self.mainConf.wordCountTimer)
|
||||
self.mainForm.addRow(
|
||||
"Word count interval",
|
||||
self.tr("Word count interval"),
|
||||
self.wordCountTimer,
|
||||
"How often the word count is updated.",
|
||||
theUnit="seconds"
|
||||
self.tr("How often the word count is updated."),
|
||||
theUnit=self.tr("seconds")
|
||||
)
|
||||
|
||||
# Writing Guides
|
||||
# ==============
|
||||
self.mainForm.addGroupLabel("Writing Guides")
|
||||
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
|
||||
|
||||
## Show Tabs and Spaces
|
||||
self.showTabsNSpaces = QSwitch()
|
||||
self.showTabsNSpaces.setChecked(self.mainConf.showTabsNSpaces)
|
||||
self.mainForm.addRow(
|
||||
"Show tabs and spaces",
|
||||
self.tr("Show tabs and spaces"),
|
||||
self.showTabsNSpaces,
|
||||
"Add symbols to indicate tabs and spaces in the editor."
|
||||
self.tr("Add symbols to indicate tabs and spaces in the editor.")
|
||||
)
|
||||
|
||||
## Show Line Endings
|
||||
self.showLineEndings = QSwitch()
|
||||
self.showLineEndings.setChecked(self.mainConf.showLineEndings)
|
||||
self.mainForm.addRow(
|
||||
"Show line endings",
|
||||
self.tr("Show line endings"),
|
||||
self.showLineEndings,
|
||||
"Add a symbol to indicate line endings in the editor."
|
||||
self.tr("Add a symbol to indicate line endings in the editor.")
|
||||
)
|
||||
|
||||
# Scroll Behaviour
|
||||
# ================
|
||||
self.mainForm.addGroupLabel("Scroll Behaviour")
|
||||
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour"))
|
||||
|
||||
## Scroll Past End
|
||||
self.scrollPastEnd = QSwitch()
|
||||
self.scrollPastEnd.setChecked(self.mainConf.scrollPastEnd)
|
||||
self.mainForm.addRow(
|
||||
"Scroll past end of the document",
|
||||
self.tr("Scroll past end of the document"),
|
||||
self.scrollPastEnd,
|
||||
"Also improves trypewriter scrolling for short documents."
|
||||
self.tr("Also improves trypewriter scrolling for short documents.")
|
||||
)
|
||||
|
||||
## Typewriter Scrolling
|
||||
self.autoScroll = QSwitch()
|
||||
self.autoScroll.setChecked(self.mainConf.autoScroll)
|
||||
self.mainForm.addRow(
|
||||
"Typewriter style scrolling when you type",
|
||||
self.tr("Typewriter style scrolling when you type"),
|
||||
self.autoScroll,
|
||||
"Try to keep the cursor at a fixed vertical position."
|
||||
self.tr("Try to keep the cursor at a fixed vertical position.")
|
||||
)
|
||||
|
||||
## Typewriter Position
|
||||
@@ -737,9 +746,9 @@ class GuiPreferencesEditor(QWidget):
|
||||
self.autoScrollPos.setSingleStep(1)
|
||||
self.autoScrollPos.setValue(int(self.mainConf.autoScrollPos))
|
||||
self.mainForm.addRow(
|
||||
"Minimum position for Typewriter scrolling",
|
||||
self.tr("Minimum position for Typewriter scrolling"),
|
||||
self.autoScrollPos,
|
||||
"Percentage of the editor height from the top.",
|
||||
self.tr("Percentage of the editor height from the top."),
|
||||
theUnit = "%"
|
||||
)
|
||||
|
||||
@@ -792,8 +801,11 @@ class GuiPreferencesEditor(QWidget):
|
||||
theDict = NWSpellSimple()
|
||||
|
||||
self.spellLangList.clear()
|
||||
for spTag, spName in theDict.listDictionaries():
|
||||
self.spellLangList.addItem(spName, spTag)
|
||||
for spTag, spProv in theDict.listDictionaries():
|
||||
qLocal = QLocale(spTag)
|
||||
spLang = qLocal.nativeLanguageName().title()
|
||||
spName = qLocal.bcp47Name()
|
||||
self.spellLangList.addItem("%s (%s) [%s]" % (spLang, spName, spProv), spTag)
|
||||
|
||||
spellIdx = self.spellLangList.findData(self.mainConf.spellLanguage)
|
||||
if spellIdx != -1:
|
||||
@@ -819,7 +831,7 @@ class GuiPreferencesSyntax(QWidget):
|
||||
|
||||
# Highlighting Theme
|
||||
# ==================
|
||||
self.mainForm.addGroupLabel("Highlighting Theme")
|
||||
self.mainForm.addGroupLabel(self.tr("Highlighting Theme"))
|
||||
|
||||
self.guiSyntax = QComboBox()
|
||||
self.guiSyntax.setMinimumWidth(self.mainConf.pxInt(200))
|
||||
@@ -831,50 +843,50 @@ class GuiPreferencesSyntax(QWidget):
|
||||
self.guiSyntax.setCurrentIndex(syntaxIdx)
|
||||
|
||||
self.mainForm.addRow(
|
||||
"Highlighting theme",
|
||||
self.tr("Highlighting theme"),
|
||||
self.guiSyntax,
|
||||
"Colour theme to apply to the editor and viewer."
|
||||
self.tr("Colour theme to apply to the editor and viewer.")
|
||||
)
|
||||
|
||||
# Quotes & Dialogue
|
||||
# =================
|
||||
self.mainForm.addGroupLabel("Quotes & Dialogue")
|
||||
self.mainForm.addGroupLabel(self.tr("Quotes & Dialogue"))
|
||||
|
||||
self.highlightQuotes = QSwitch()
|
||||
self.highlightQuotes.setChecked(self.mainConf.highlightQuotes)
|
||||
self.highlightQuotes.toggled.connect(self._toggleHighlightQuotes)
|
||||
self.mainForm.addRow(
|
||||
"Highlight text wrapped in quotes",
|
||||
self.tr("Highlight text wrapped in quotes"),
|
||||
self.highlightQuotes,
|
||||
"Applies to single, double and straight quotes."
|
||||
self.tr("Applies to single, double and straight quotes.")
|
||||
)
|
||||
|
||||
self.allowOpenSQuote = QSwitch()
|
||||
self.allowOpenSQuote.setChecked(self.mainConf.allowOpenSQuote)
|
||||
self.mainForm.addRow(
|
||||
"Allow open-ended single quotes",
|
||||
self.tr("Allow open-ended single quotes"),
|
||||
self.allowOpenSQuote,
|
||||
"Highlight single-quoted line with no closing quote."
|
||||
self.tr("Highlight single-quoted line with no closing quote.")
|
||||
)
|
||||
|
||||
self.allowOpenDQuote = QSwitch()
|
||||
self.allowOpenDQuote.setChecked(self.mainConf.allowOpenDQuote)
|
||||
self.mainForm.addRow(
|
||||
"Allow open-ended double quotes",
|
||||
self.tr("Allow open-ended double quotes"),
|
||||
self.allowOpenDQuote,
|
||||
"Highlight double-quoted line with no closing quote."
|
||||
self.tr("Highlight double-quoted line with no closing quote.")
|
||||
)
|
||||
|
||||
# Text Emphasis
|
||||
# =============
|
||||
self.mainForm.addGroupLabel("Text Emphasis")
|
||||
self.mainForm.addGroupLabel(self.tr("Text Emphasis"))
|
||||
|
||||
self.highlightEmph = QSwitch()
|
||||
self.highlightEmph.setChecked(self.mainConf.highlightEmph)
|
||||
self.mainForm.addRow(
|
||||
"Add highlight colour to emphasised text",
|
||||
self.tr("Add highlight colour to emphasised text"),
|
||||
self.highlightEmph,
|
||||
"Applies to emphasis (italic) and strong (bold)."
|
||||
self.tr("Applies to emphasis (italic) and strong (bold).")
|
||||
)
|
||||
|
||||
return
|
||||
@@ -927,15 +939,15 @@ class GuiPreferencesAutomation(QWidget):
|
||||
|
||||
# Automatic Features
|
||||
# ==================
|
||||
self.mainForm.addGroupLabel("Automatic Features")
|
||||
self.mainForm.addGroupLabel(self.tr("Automatic Features"))
|
||||
|
||||
## Auto-Select Word Under Cursor
|
||||
self.autoSelect = QSwitch()
|
||||
self.autoSelect.setChecked(self.mainConf.autoSelect)
|
||||
self.mainForm.addRow(
|
||||
"Auto-select word under cursor",
|
||||
self.tr("Auto-select word under cursor"),
|
||||
self.autoSelect,
|
||||
"Apply formatting to word under cursor if no selection is made."
|
||||
self.tr("Apply formatting to word under cursor if no selection is made.")
|
||||
)
|
||||
|
||||
## Auto-Replace as You Type Main Switch
|
||||
@@ -943,23 +955,23 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.doReplace.setChecked(self.mainConf.doReplace)
|
||||
self.doReplace.toggled.connect(self._toggleAutoReplaceMain)
|
||||
self.mainForm.addRow(
|
||||
"Auto-replace text as you type",
|
||||
self.tr("Auto-replace text as you type"),
|
||||
self.doReplace,
|
||||
"Allow the editor to replace symbols as you type."
|
||||
self.tr("Allow the editor to replace symbols as you type.")
|
||||
)
|
||||
|
||||
# Replace as You Type
|
||||
# ===================
|
||||
self.mainForm.addGroupLabel("Replace as You Type")
|
||||
self.mainForm.addGroupLabel(self.tr("Replace as You Type"))
|
||||
|
||||
## Auto-Replace Single Quotes
|
||||
self.doReplaceSQuote = QSwitch()
|
||||
self.doReplaceSQuote.setChecked(self.mainConf.doReplaceSQuote)
|
||||
self.doReplaceSQuote.setEnabled(self.mainConf.doReplace)
|
||||
self.mainForm.addRow(
|
||||
"Auto-replace single quotes",
|
||||
self.tr("Auto-replace single quotes"),
|
||||
self.doReplaceSQuote,
|
||||
"Try to guess which is an opening or a closing single quote."
|
||||
self.tr("Try to guess which is an opening or a closing single quote.")
|
||||
)
|
||||
|
||||
## Auto-Replace Double Quotes
|
||||
@@ -967,9 +979,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.doReplaceDQuote.setChecked(self.mainConf.doReplaceDQuote)
|
||||
self.doReplaceDQuote.setEnabled(self.mainConf.doReplace)
|
||||
self.mainForm.addRow(
|
||||
"Auto-replace double quotes",
|
||||
self.tr("Auto-replace double quotes"),
|
||||
self.doReplaceDQuote,
|
||||
"Try to guess which is an opening or a closing double quote."
|
||||
self.tr("Try to guess which is an opening or a closing double quote.")
|
||||
)
|
||||
|
||||
## Auto-Replace Hyphens
|
||||
@@ -977,9 +989,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.doReplaceDash.setChecked(self.mainConf.doReplaceDash)
|
||||
self.doReplaceDash.setEnabled(self.mainConf.doReplace)
|
||||
self.mainForm.addRow(
|
||||
"Auto-replace dashes",
|
||||
self.tr("Auto-replace dashes"),
|
||||
self.doReplaceDash,
|
||||
"Double and triple hyphens become short and long dashes."
|
||||
self.tr("Double and triple hyphens become short and long dashes.")
|
||||
)
|
||||
|
||||
## Auto-Replace Dots
|
||||
@@ -987,14 +999,14 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.doReplaceDots.setChecked(self.mainConf.doReplaceDots)
|
||||
self.doReplaceDots.setEnabled(self.mainConf.doReplace)
|
||||
self.mainForm.addRow(
|
||||
"Auto-replace dots",
|
||||
self.tr("Auto-replace dots"),
|
||||
self.doReplaceDots,
|
||||
"Three consecutive dots become ellipsis."
|
||||
self.tr("Three consecutive dots become ellipsis.")
|
||||
)
|
||||
|
||||
# Quotation Style
|
||||
# ===============
|
||||
self.mainForm.addGroupLabel("Quotation Style")
|
||||
self.mainForm.addGroupLabel(self.tr("Quotation Style"))
|
||||
|
||||
qWidth = self.mainConf.pxInt(40)
|
||||
bWidth = int(2.5*self.theTheme.getTextWidth("..."))
|
||||
@@ -1011,9 +1023,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.btnSingleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
|
||||
self.mainForm.addRow(
|
||||
"Single quote open style",
|
||||
self.tr("Single quote open style"),
|
||||
self.quoteSym["SO"],
|
||||
"The symbol to use for a leading single quote.",
|
||||
self.tr("The symbol to use for a leading single quote."),
|
||||
theButton=self.btnSingleStyleO
|
||||
)
|
||||
|
||||
@@ -1027,9 +1039,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.btnSingleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
|
||||
self.mainForm.addRow(
|
||||
"Single quote close style",
|
||||
self.tr("Single quote close style"),
|
||||
self.quoteSym["SC"],
|
||||
"The symbol to use for a trailing single quote.",
|
||||
self.tr("The symbol to use for a trailing single quote."),
|
||||
theButton=self.btnSingleStyleC
|
||||
)
|
||||
|
||||
@@ -1044,9 +1056,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.btnDoubleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
|
||||
self.mainForm.addRow(
|
||||
"Double quote open style",
|
||||
self.tr("Double quote open style"),
|
||||
self.quoteSym["DO"],
|
||||
"The symbol to use for a leading double quote.",
|
||||
self.tr("The symbol to use for a leading double quote."),
|
||||
theButton=self.btnDoubleStyleO
|
||||
)
|
||||
|
||||
@@ -1060,9 +1072,9 @@ class GuiPreferencesAutomation(QWidget):
|
||||
self.btnDoubleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
|
||||
self.mainForm.addRow(
|
||||
"Double quote close style",
|
||||
self.tr("Double quote close style"),
|
||||
self.quoteSym["DC"],
|
||||
"The symbol to use for a trailing double quote.",
|
||||
self.tr("The symbol to use for a trailing double quote."),
|
||||
theButton=self.btnDoubleStyleC
|
||||
)
|
||||
|
||||
|
||||
+30
-20
@@ -54,7 +54,7 @@ class GuiProjectDetails(PagedDialog):
|
||||
self.theProject = theProject
|
||||
self.optState = theProject.optState
|
||||
|
||||
self.setWindowTitle("Project Details")
|
||||
self.setWindowTitle(self.tr("Project Details"))
|
||||
|
||||
wW = self.mainConf.pxInt(600)
|
||||
wH = self.mainConf.pxInt(400)
|
||||
@@ -69,10 +69,11 @@ class GuiProjectDetails(PagedDialog):
|
||||
self.tabMain = GuiProjectDetailsMain(self.theParent, self.theProject)
|
||||
self.tabContents = GuiProjectDetailsContents(self.theParent, self.theProject)
|
||||
|
||||
self.addTab(self.tabMain, "Overview")
|
||||
self.addTab(self.tabContents, "Contents")
|
||||
self.addTab(self.tabMain, self.tr("Overview"))
|
||||
self.addTab(self.tabContents, self.tr("Contents"))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
self.buttonBox.button(QDialogButtonBox.Close).setText(self.tr("Close"))
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.addControls(self.buttonBox)
|
||||
|
||||
@@ -154,7 +155,9 @@ class GuiProjectDetailsMain(QWidget):
|
||||
self.bookTitle.setAlignment(Qt.AlignHCenter)
|
||||
self.bookTitle.setWordWrap(True)
|
||||
|
||||
self.projName = QLabel("Working Title: %s" % self.theProject.projName)
|
||||
self.projName = QLabel(
|
||||
self.tr("Working Title: {0}").format(self.theProject.projName)
|
||||
)
|
||||
workFont = self.projName.font()
|
||||
workFont.setPointSizeF(0.8*fPt)
|
||||
workFont.setItalic(True)
|
||||
@@ -162,7 +165,7 @@ class GuiProjectDetailsMain(QWidget):
|
||||
self.projName.setAlignment(Qt.AlignHCenter)
|
||||
self.projName.setWordWrap(True)
|
||||
|
||||
self.bookAuthors = QLabel("By %s" % self.theProject.getAuthors())
|
||||
self.bookAuthors = QLabel(self.tr("By {0}").format(self.theProject.getAuthors()))
|
||||
authFont = self.bookAuthors.font()
|
||||
authFont.setPointSizeF(1.2*fPt)
|
||||
self.bookAuthors.setFont(authFont)
|
||||
@@ -175,20 +178,20 @@ class GuiProjectDetailsMain(QWidget):
|
||||
hCounts = self.theIndex.getNovelTitleCounts()
|
||||
nwCount = self.theIndex.getNovelWordCount()
|
||||
|
||||
self.wordCountLbl = QLabel("<b>Words:</b>")
|
||||
self.wordCountLbl = QLabel("<b>%s:</b>" % self.tr("Words"))
|
||||
self.wordCountVal = QLabel(f"{nwCount:n}")
|
||||
|
||||
self.chapCountLbl = QLabel("<b>Chapters:</b>")
|
||||
self.chapCountLbl = QLabel("<b>%s:</b>" % self.tr("Chapters"))
|
||||
self.chapCountVal = QLabel(f"{hCounts[2]:n}")
|
||||
|
||||
self.sceneCountLbl = QLabel("<b>Scenes:</b>")
|
||||
self.sceneCountLbl = QLabel("<b>%s:</b>" % self.tr("Scenes"))
|
||||
self.sceneCountVal = QLabel(f"{hCounts[3]:n}")
|
||||
|
||||
self.revCountLbl = QLabel("<b>Revisions:</b>")
|
||||
self.revCountLbl = QLabel("<b>%s:</b>" % self.tr("Revisions"))
|
||||
self.revCountVal = QLabel(f"{self.theProject.saveCount:n}")
|
||||
|
||||
edTime = self.theProject.getCurrentEditTime()
|
||||
self.editTimeLbl = QLabel("<b>Editing Time:</b>")
|
||||
self.editTimeLbl = QLabel("<b>%s:</b>" % self.tr("Editing Time"))
|
||||
self.editTimeVal = QLabel(f"{edTime//3600:02d}:{edTime%3600//60:02d}")
|
||||
|
||||
self.statsGrid = QGridLayout()
|
||||
@@ -208,7 +211,7 @@ class GuiProjectDetailsMain(QWidget):
|
||||
# Meta
|
||||
# ====
|
||||
|
||||
self.projPathLbl = QLabel("<b>Path:</b>")
|
||||
self.projPathLbl = QLabel("<b>%s:</b>" % self.tr("Path"))
|
||||
self.projPathVal = QLineEdit()
|
||||
self.projPathVal.setText(self.theProject.projPath)
|
||||
self.projPathVal.setReadOnly(True)
|
||||
@@ -271,7 +274,14 @@ class GuiProjectDetailsContents(QWidget):
|
||||
self.tocTree.setIndentation(0)
|
||||
self.tocTree.setColumnCount(6)
|
||||
self.tocTree.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
self.tocTree.setHeaderLabels(["Title", "Words", "Pages", "Page", "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)
|
||||
@@ -304,16 +314,16 @@ class GuiProjectDetailsContents(QWidget):
|
||||
clearDouble = self.optState.getInt("GuiProjectDetails", "clearDouble", True)
|
||||
|
||||
wordsHelp = (
|
||||
"Typical word count for a 5 by 8 inch book page with 11 pt font is 350."
|
||||
self.tr("Typical word count for a 5 by 8 inch book page with 11 pt font is 350.")
|
||||
)
|
||||
offsetHelp = (
|
||||
"Start counting page numbers from this page."
|
||||
self.tr("Start counting page numbers from this page.")
|
||||
)
|
||||
dblHelp = (
|
||||
"Assume a new chapter or partition always start on an odd numbered page."
|
||||
self.tr("Assume a new chapter or partition always start on an odd numbered page.")
|
||||
)
|
||||
|
||||
self.wpLabel = QLabel("Words per page")
|
||||
self.wpLabel = QLabel(self.tr("Words per page"))
|
||||
self.wpLabel.setToolTip(wordsHelp)
|
||||
|
||||
self.wpValue = QSpinBox()
|
||||
@@ -324,7 +334,7 @@ class GuiProjectDetailsContents(QWidget):
|
||||
self.wpValue.setToolTip(wordsHelp)
|
||||
self.wpValue.valueChanged.connect(self._populateTree)
|
||||
|
||||
self.poLabel = QLabel("Count pages from")
|
||||
self.poLabel = QLabel(self.tr("Count pages from"))
|
||||
self.poLabel.setToolTip(offsetHelp)
|
||||
|
||||
self.poValue = QSpinBox()
|
||||
@@ -335,7 +345,7 @@ class GuiProjectDetailsContents(QWidget):
|
||||
self.poValue.setToolTip(offsetHelp)
|
||||
self.poValue.valueChanged.connect(self._populateTree)
|
||||
|
||||
self.dblLabel = QLabel("Clear double pages")
|
||||
self.dblLabel = QLabel(self.tr("Clear double pages"))
|
||||
self.dblLabel.setToolTip(dblHelp)
|
||||
|
||||
self.dblValue = QSwitch(self, 2*iPx, iPx)
|
||||
@@ -358,7 +368,7 @@ class GuiProjectDetailsContents(QWidget):
|
||||
# ========
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addWidget(QLabel("<b>Table of Contents</b>"))
|
||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % self.tr("Table of Contents")))
|
||||
self.outerBox.addWidget(self.tocTree)
|
||||
self.outerBox.addLayout(self.optionsBox)
|
||||
|
||||
@@ -390,7 +400,7 @@ class GuiProjectDetailsContents(QWidget):
|
||||
"""
|
||||
self._theToC = []
|
||||
self._theToC = self.theIndex.getTableOfContents(2)
|
||||
self._theToC.append(("", 0, "END", 0))
|
||||
self._theToC.append(("", 0, self.tr("END"), 0))
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
+25
-13
@@ -74,7 +74,7 @@ class GuiProjectLoad(QDialog):
|
||||
self.outerBox.setSpacing(sPx)
|
||||
self.innerBox.setSpacing(sPx)
|
||||
|
||||
self.setWindowTitle("Open Project")
|
||||
self.setWindowTitle(self.tr("Open Project"))
|
||||
self.setMinimumWidth(self.mainConf.pxInt(650))
|
||||
self.setMinimumHeight(self.mainConf.pxInt(400))
|
||||
self.setModal(True)
|
||||
@@ -90,7 +90,11 @@ class GuiProjectLoad(QDialog):
|
||||
self.listBox.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
|
||||
self.listBox.setColumnCount(3)
|
||||
self.listBox.setHeaderLabels(["Working Title", "Words", "Last Opened"])
|
||||
self.listBox.setHeaderLabels([
|
||||
self.tr("Working Title"),
|
||||
self.tr("Words"),
|
||||
self.tr("Last Opened"),
|
||||
])
|
||||
self.listBox.setRootIsDecorated(False)
|
||||
self.listBox.itemSelectionChanged.connect(self._doSelectRecent)
|
||||
self.listBox.itemDoubleClicked.connect(self._doOpenRecent)
|
||||
@@ -100,8 +104,8 @@ class GuiProjectLoad(QDialog):
|
||||
treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight)
|
||||
treeHead.setTextAlignment(self.C_TIME, Qt.AlignRight)
|
||||
|
||||
self.lblRecent = QLabel("<b>Recently Opened Projects</b>")
|
||||
self.lblPath = QLabel("<b>Path</b>")
|
||||
self.lblRecent = QLabel("<b>%s</b>" % self.tr("Recently Opened Projects"))
|
||||
self.lblPath = QLabel("<b>%s</b>" % self.tr("Path"))
|
||||
self.selPath = QLineEdit("")
|
||||
self.selPath.setReadOnly(True)
|
||||
|
||||
@@ -123,13 +127,15 @@ class GuiProjectLoad(QDialog):
|
||||
self.innerBox.addLayout(self.projectForm)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Open | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Open).setText(self.tr("Open"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doOpenRecent)
|
||||
self.buttonBox.rejected.connect(self._doCancel)
|
||||
|
||||
self.newButton = self.buttonBox.addButton("New", QDialogButtonBox.ActionRole)
|
||||
self.newButton = self.buttonBox.addButton(self.tr("New"), QDialogButtonBox.ActionRole)
|
||||
self.newButton.clicked.connect(self._doNewProject)
|
||||
|
||||
self.delButton = self.buttonBox.addButton("Remove", QDialogButtonBox.ActionRole)
|
||||
self.delButton = self.buttonBox.addButton(self.tr("Remove"), QDialogButtonBox.ActionRole)
|
||||
self.delButton.clicked.connect(self._doDeleteRecent)
|
||||
|
||||
self.outerBox.addLayout(self.innerBox)
|
||||
@@ -180,12 +186,15 @@ class GuiProjectLoad(QDialog):
|
||||
"""Browse for a folder path.
|
||||
"""
|
||||
logger.verbose("GuiProjectLoad browse button clicked")
|
||||
extFilter = [
|
||||
self.tr("novelWriter Project File ({0})").format(nwFiles.PROJ_FILE),
|
||||
self.tr("All files ({0})").format("*.*"),
|
||||
]
|
||||
dlgOpt = QFileDialog.Options()
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
projFile, _ = QFileDialog.getOpenFileName(
|
||||
self, "Open novelWriter Project", "",
|
||||
"novelWriter Project File (%s);;All Files (*)" % nwFiles.PROJ_FILE,
|
||||
options=dlgOpt
|
||||
self, self.tr("Open novelWriter Project"), "",
|
||||
filter=";;".join(extFilter), options=dlgOpt
|
||||
)
|
||||
if projFile:
|
||||
thePath = os.path.abspath(os.path.dirname(projFile))
|
||||
@@ -221,10 +230,13 @@ class GuiProjectLoad(QDialog):
|
||||
selList = self.listBox.selectedItems()
|
||||
if selList:
|
||||
projName = selList[0].text(self.C_NAME)
|
||||
msgYes = self.theParent.askQuestion("Remove Entry", (
|
||||
"Remove '%s' from the recent projects list? "
|
||||
"The project files will not be deleted."
|
||||
) % projName)
|
||||
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)
|
||||
)
|
||||
if msgYes:
|
||||
self.mainConf.removeFromRecentCache(
|
||||
selList[0].data(self.C_NAME, Qt.UserRole)
|
||||
|
||||
+44
-34
@@ -54,7 +54,7 @@ class GuiProjectSettings(PagedDialog):
|
||||
self.optState = theProject.optState
|
||||
|
||||
self.theProject.countStatus()
|
||||
self.setWindowTitle("Project Settings")
|
||||
self.setWindowTitle(self.tr("Project Settings"))
|
||||
|
||||
wW = self.mainConf.pxInt(570)
|
||||
wH = self.mainConf.pxInt(375)
|
||||
@@ -71,12 +71,14 @@ class GuiProjectSettings(PagedDialog):
|
||||
self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject, False)
|
||||
self.tabReplace = GuiProjectEditReplace(self.theParent, self.theProject)
|
||||
|
||||
self.addTab(self.tabMain, "Settings")
|
||||
self.addTab(self.tabStatus, "Status")
|
||||
self.addTab(self.tabImport, "Importance")
|
||||
self.addTab(self.tabReplace, "Auto-Replace")
|
||||
self.addTab(self.tabMain, self.tr("Settings"))
|
||||
self.addTab(self.tabStatus, self.tr("Status"))
|
||||
self.addTab(self.tabImport, self.tr("Importance"))
|
||||
self.addTab(self.tabReplace, self.tr("Auto-Replace"))
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Ok"))
|
||||
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
self.addControls(self.buttonBox)
|
||||
@@ -166,7 +168,7 @@ class GuiProjectEditMain(QWidget):
|
||||
self.mainForm.setHelpTextStyle(self.theParent.theTheme.helpText)
|
||||
self.setLayout(self.mainForm)
|
||||
|
||||
self.mainForm.addGroupLabel("Project Settings")
|
||||
self.mainForm.addGroupLabel(self.tr("Project Settings"))
|
||||
|
||||
xW = self.mainConf.pxInt(250)
|
||||
xH = self.mainConf.pxInt(100)
|
||||
@@ -176,9 +178,9 @@ class GuiProjectEditMain(QWidget):
|
||||
self.editName.setFixedWidth(xW)
|
||||
self.editName.setText(self.theProject.projName)
|
||||
self.mainForm.addRow(
|
||||
"Working title",
|
||||
self.tr("Working title"),
|
||||
self.editName,
|
||||
"Should be set only once."
|
||||
self.tr("Should be set only once.")
|
||||
)
|
||||
|
||||
self.editTitle = QLineEdit()
|
||||
@@ -186,9 +188,9 @@ class GuiProjectEditMain(QWidget):
|
||||
self.editTitle.setFixedWidth(xW)
|
||||
self.editTitle.setText(self.theProject.bookTitle)
|
||||
self.mainForm.addRow(
|
||||
"Novel title",
|
||||
self.tr("Novel title"),
|
||||
self.editTitle,
|
||||
"Change whenever you want!"
|
||||
self.tr("Change whenever you want!")
|
||||
)
|
||||
|
||||
self.editAuthors = QPlainTextEdit()
|
||||
@@ -199,22 +201,22 @@ class GuiProjectEditMain(QWidget):
|
||||
self.editAuthors.setFixedHeight(xH)
|
||||
self.editAuthors.setFixedWidth(xW)
|
||||
self.mainForm.addRow(
|
||||
"Author(s)",
|
||||
self.tr("Author(s)"),
|
||||
self.editAuthors,
|
||||
"One name per line."
|
||||
self.tr("One name per line.")
|
||||
)
|
||||
|
||||
self.spellLang = QComboBox(self)
|
||||
theDict = self.theParent.docEditor.theDict
|
||||
self.spellLang.addItem("Default", "None")
|
||||
self.spellLang.addItem(self.tr("Default"), "None")
|
||||
if theDict is not None:
|
||||
for spTag, spName in theDict.listDictionaries():
|
||||
self.spellLang.addItem(spName, spTag)
|
||||
|
||||
self.mainForm.addRow(
|
||||
"Spell check language",
|
||||
self.tr("Spell check language"),
|
||||
self.spellLang,
|
||||
"Overrides main preferences."
|
||||
self.tr("Overrides main preferences.")
|
||||
)
|
||||
|
||||
spellIdx = 0
|
||||
@@ -226,9 +228,9 @@ class GuiProjectEditMain(QWidget):
|
||||
self.doBackup = QSwitch(self)
|
||||
self.doBackup.setChecked(not self.theProject.doBackup)
|
||||
self.mainForm.addRow(
|
||||
"No backup on close",
|
||||
self.tr("No backup on close"),
|
||||
self.doBackup,
|
||||
"Overrides main preferences."
|
||||
self.tr("Overrides main preferences.")
|
||||
)
|
||||
|
||||
return
|
||||
@@ -271,12 +273,12 @@ class GuiProjectEditStatus(QWidget):
|
||||
self.editName = QLineEdit()
|
||||
self.editName.setMaxLength(40)
|
||||
self.editName.setEnabled(False)
|
||||
self.newButton = QPushButton("New")
|
||||
self.delButton = QPushButton("Delete")
|
||||
self.saveButton = QPushButton("Save")
|
||||
self.newButton = QPushButton(self.tr("New"))
|
||||
self.delButton = QPushButton(self.tr("Delete"))
|
||||
self.saveButton = QPushButton(self.tr("Save"))
|
||||
self.colPixmap = QPixmap(self.iPx, self.iPx)
|
||||
self.colPixmap.fill(QColor(120, 120, 120))
|
||||
self.colButton = QPushButton(QIcon(self.colPixmap), "Colour")
|
||||
self.colButton = QPushButton(QIcon(self.colPixmap), self.tr("Colour"))
|
||||
self.colButton.setIconSize(self.colPixmap.rect().size())
|
||||
|
||||
self.newButton.clicked.connect(self._newItem)
|
||||
@@ -287,7 +289,7 @@ class GuiProjectEditStatus(QWidget):
|
||||
self.mainForm.addWidget(self.newButton)
|
||||
self.mainForm.addWidget(self.delButton)
|
||||
self.mainForm.addStretch(1)
|
||||
self.mainForm.addWidget(QLabel("<b>Name</b>"))
|
||||
self.mainForm.addWidget(QLabel("<b>%s</b>" % self.tr("Name")))
|
||||
self.mainForm.addWidget(self.editName)
|
||||
self.mainForm.addWidget(self.colButton)
|
||||
self.mainForm.addStretch(1)
|
||||
@@ -297,9 +299,9 @@ class GuiProjectEditStatus(QWidget):
|
||||
self.mainBox.addLayout(self.mainForm)
|
||||
|
||||
if isStatus:
|
||||
self.outerBox.addWidget(QLabel("<b>Novel File Status Levels</b>"))
|
||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % self.tr("Novel File Status Levels")))
|
||||
else:
|
||||
self.outerBox.addWidget(QLabel("<b>Note File Importance Levels</b>"))
|
||||
self.outerBox.addWidget(QLabel("<b>%s</b>" % self.tr("Note File Importance Levels")))
|
||||
self.outerBox.addLayout(self.mainBox)
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
@@ -325,7 +327,8 @@ class GuiProjectEditStatus(QWidget):
|
||||
"""
|
||||
if self.selColour is not None:
|
||||
newCol = QColorDialog.getColor(
|
||||
self.selColour, self, "Select Colour", QColorDialog.DontUseNativeDialog
|
||||
self.selColour, self, self.tr("Select Colour"),
|
||||
QColorDialog.DontUseNativeDialog
|
||||
)
|
||||
if newCol.isValid():
|
||||
self.selColour = newCol
|
||||
@@ -338,7 +341,7 @@ class GuiProjectEditStatus(QWidget):
|
||||
def _newItem(self):
|
||||
"""Create a new status item.
|
||||
"""
|
||||
newItem = self._addItem("New Item", (0, 0, 0), None, 0)
|
||||
newItem = self._addItem(self.tr("New Item"), (0, 0, 0), None, 0)
|
||||
newItem.setBackground(QBrush(QColor(0, 255, 0, 80)))
|
||||
self.colChanged = True
|
||||
return
|
||||
@@ -355,7 +358,7 @@ class GuiProjectEditStatus(QWidget):
|
||||
self.colChanged = True
|
||||
else:
|
||||
self.theParent.makeAlert(
|
||||
"Cannot delete status item that is in use.", nwAlert.ERROR
|
||||
self.tr("Cannot delete status item that is in use."), nwAlert.ERROR
|
||||
)
|
||||
return
|
||||
|
||||
@@ -372,7 +375,9 @@ class GuiProjectEditStatus(QWidget):
|
||||
self.selColour.blue(),
|
||||
self.colData[selIdx][4]
|
||||
)
|
||||
selItem.setText("%s [%d]" % (self.colData[selIdx][0], self.colCounts[selIdx]))
|
||||
selItem.setText(self.tr("{0} [{1}]").format(
|
||||
self.colData[selIdx][0], self.colCounts[selIdx])
|
||||
)
|
||||
selItem.setIcon(self.colButton.icon())
|
||||
self.editName.setEnabled(False)
|
||||
self.colChanged = True
|
||||
@@ -384,7 +389,7 @@ class GuiProjectEditStatus(QWidget):
|
||||
newIcon = QPixmap(self.iPx, self.iPx)
|
||||
newIcon.fill(QColor(*iCol))
|
||||
newItem = QListWidgetItem()
|
||||
newItem.setText("%s [%d]" % (iName, nUse))
|
||||
newItem.setText(self.tr("{0} [{1}]").format(iName, nUse))
|
||||
newItem.setIcon(QIcon(newIcon))
|
||||
newItem.setData(Qt.UserRole, len(self.colData))
|
||||
self.listBox.addItem(newItem)
|
||||
@@ -450,7 +455,10 @@ class GuiProjectEditReplace(QWidget):
|
||||
self.optState.getInt("GuiProjectSettings", "replaceColW", 100)
|
||||
)
|
||||
self.listBox = QTreeWidget()
|
||||
self.listBox.setHeaderLabels(["Keyword", "Replace With"])
|
||||
self.listBox.setHeaderLabels([
|
||||
self.tr("Keyword"),
|
||||
self.tr("Replace With"),
|
||||
])
|
||||
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
||||
self.listBox.setColumnWidth(0, wCol0)
|
||||
self.listBox.setIndentation(0)
|
||||
@@ -467,9 +475,9 @@ class GuiProjectEditReplace(QWidget):
|
||||
self.saveButton = QPushButton(self.theTheme.getIcon("done"), "")
|
||||
self.addButton = QPushButton(self.theTheme.getIcon("add"), "")
|
||||
self.delButton = QPushButton(self.theTheme.getIcon("remove"), "")
|
||||
self.saveButton.setToolTip("Save entry")
|
||||
self.addButton.setToolTip("Add new entry")
|
||||
self.delButton.setToolTip("Delete selected entry")
|
||||
self.saveButton.setToolTip(self.tr("Save entry"))
|
||||
self.addButton.setToolTip(self.tr("Add new entry"))
|
||||
self.delButton.setToolTip(self.tr("Delete selected entry"))
|
||||
|
||||
self.editKey.setEnabled(False)
|
||||
self.editKey.setMaxLength(40)
|
||||
@@ -486,7 +494,9 @@ class GuiProjectEditReplace(QWidget):
|
||||
self.bottomBox.addWidget(self.addButton)
|
||||
self.bottomBox.addWidget(self.delButton)
|
||||
|
||||
self.outerBox.addWidget(QLabel("<b>Text Replace List for Preview and Export</b>"))
|
||||
self.outerBox.addWidget(
|
||||
QLabel("<b>%s</b>" % self.tr("Text Replace List for Preview and Export"))
|
||||
)
|
||||
self.outerBox.addWidget(self.listBox)
|
||||
self.outerBox.addLayout(self.bottomBox)
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
+48
-37
@@ -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__)
|
||||
@@ -85,14 +86,19 @@ class GuiProjectTree(QTreeWidget):
|
||||
self.setExpandsOnDoubleClick(True)
|
||||
self.setIndentation(iPx)
|
||||
self.setColumnCount(4)
|
||||
self.setHeaderLabels(["Label", "Words", "Inc", "Flags"])
|
||||
self.setHeaderLabels([
|
||||
self.tr("Label"),
|
||||
self.tr("Words"),
|
||||
self.tr("Inc"),
|
||||
self.tr("Flags")
|
||||
])
|
||||
|
||||
treeHeadItem = self.headerItem()
|
||||
treeHeadItem.setTextAlignment(self.C_COUNT, Qt.AlignRight)
|
||||
treeHeadItem.setToolTip(self.C_NAME, "Item label")
|
||||
treeHeadItem.setToolTip(self.C_COUNT, "Word count")
|
||||
treeHeadItem.setToolTip(self.C_EXPORT, "Include in build")
|
||||
treeHeadItem.setToolTip(self.C_FLAGS, "Status, class, and layout flags")
|
||||
treeHeadItem.setToolTip(self.C_NAME, self.tr("Item label"))
|
||||
treeHeadItem.setToolTip(self.C_COUNT, self.tr("Word count"))
|
||||
treeHeadItem.setToolTip(self.C_EXPORT, self.tr("Include in build"))
|
||||
treeHeadItem.setToolTip(self.C_FLAGS, self.tr("Status, class, and layout flags"))
|
||||
|
||||
# Let the last column stretch, and set the minimum size to the
|
||||
# size of the icon as the default Qt font metrics approach fails
|
||||
@@ -193,12 +199,12 @@ class GuiProjectTree(QTreeWidget):
|
||||
if itemClass is None:
|
||||
if itemType == nwItemType.FILE:
|
||||
self.makeAlert(
|
||||
"Please select a valid location in the tree to add the document.",
|
||||
self.tr("Please select a valid location in the tree to add the document."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
else:
|
||||
self.makeAlert(
|
||||
"Please select a valid location in the tree to add the folder.",
|
||||
self.tr("Please select a valid location in the tree to add the folder."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
@@ -209,7 +215,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
)
|
||||
|
||||
if itemType == nwItemType.ROOT:
|
||||
tHandle = self.theProject.newRoot(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
|
||||
@@ -223,7 +229,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
# If still nothing, give up
|
||||
if pHandle is None:
|
||||
self.makeAlert(
|
||||
"Did not find anywhere to add the file or folder!", nwAlert.ERROR
|
||||
self.tr("Did not find anywhere to add the file or folder!"), nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -237,14 +243,14 @@ class GuiProjectTree(QTreeWidget):
|
||||
# If we again have no home, give up
|
||||
if pHandle is None:
|
||||
self.makeAlert(
|
||||
"Did not find anywhere to add the file or folder!", nwAlert.ERROR
|
||||
self.tr("Did not find anywhere to add the file or folder!"), nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
if self.theProject.projTree.isTrashRoot(pHandle):
|
||||
self.makeAlert(
|
||||
"Cannot add new files or folders to the %s folder." % (
|
||||
nwLabels.CLASS_NAME[nwItemClass.TRASH]
|
||||
self.tr("Cannot add new files or folders to the {0} folder.").format(
|
||||
trConst(nwLabels.CLASS_NAME[nwItemClass.TRASH])
|
||||
), nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
@@ -253,18 +259,18 @@ class GuiProjectTree(QTreeWidget):
|
||||
|
||||
# If we're still here, add the file or folder
|
||||
if itemType == nwItemType.FILE:
|
||||
tHandle = self.theProject.newFile("New File", itemClass, pHandle)
|
||||
tHandle = self.theProject.newFile(self.tr("New File"), itemClass, pHandle)
|
||||
|
||||
elif itemType == nwItemType.FOLDER:
|
||||
if len(parTree) >= nwConst.MAX_DEPTH - 1:
|
||||
# Folders cannot be deeper than MAX_DEPTH - 1, leaving room
|
||||
# for one more level of files.
|
||||
self.makeAlert((
|
||||
"Cannot add new folder to this item. "
|
||||
"Maximum folder depth has been reached."
|
||||
self.tr("Cannot add new folder to this item."),
|
||||
self.tr("Maximum folder depth has been reached.")
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
tHandle = self.theProject.newFolder("New Folder", itemClass, pHandle)
|
||||
tHandle = self.theProject.newFolder(self.tr("New Folder"), itemClass, pHandle)
|
||||
|
||||
else:
|
||||
logger.error("Failed to add new item")
|
||||
@@ -428,7 +434,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
logger.debug("Emptying Trash folder")
|
||||
if trashHandle is None:
|
||||
self.makeAlert(
|
||||
"There is currently no Trash folder in this project.", nwAlert.INFO
|
||||
self.tr("There is currently no Trash folder in this project."), nwAlert.INFO
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -438,11 +444,12 @@ class GuiProjectTree(QTreeWidget):
|
||||
|
||||
nTrash = len(theTrash)
|
||||
if nTrash == 0:
|
||||
self.makeAlert("The Trash folder is already empty.", nwAlert.INFO)
|
||||
self.makeAlert(self.tr("The Trash folder is already empty."), nwAlert.INFO)
|
||||
return False
|
||||
|
||||
msgYes = self.askQuestion(
|
||||
"Empty Trash", "Permanently delete %d file(s) from Trash?" % nTrash
|
||||
self.tr("Empty Trash"),
|
||||
self.tr("Permanently delete {0} file(s) from Trash?").format(nTrash)
|
||||
)
|
||||
if not msgYes:
|
||||
return False
|
||||
@@ -500,7 +507,8 @@ class GuiProjectTree(QTreeWidget):
|
||||
doPermanent = False
|
||||
if not alreadyAsked:
|
||||
msgYes = self.askQuestion(
|
||||
"Delete File", "Permanently delete file '%s'?" % nwItemS.itemName
|
||||
self.tr("Delete File"),
|
||||
self.tr("Permanently delete file '{0}'?").format(nwItemS.itemName)
|
||||
)
|
||||
if msgYes:
|
||||
doPermanent = True
|
||||
@@ -529,7 +537,8 @@ class GuiProjectTree(QTreeWidget):
|
||||
doTrash = False
|
||||
if askForTrash:
|
||||
msgYes = self.askQuestion(
|
||||
"Delete File", "Move file '%s' to Trash?" % nwItemS.itemName
|
||||
self.tr("Delete File"),
|
||||
self.tr("Move file '{0}' to Trash?").format(nwItemS.itemName),
|
||||
)
|
||||
if msgYes:
|
||||
doTrash = True
|
||||
@@ -563,7 +572,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
self._deleteTreeItem(tHandle)
|
||||
self._setTreeChanged(True)
|
||||
else:
|
||||
self.makeAlert((
|
||||
self.makeAlert(self.tr(
|
||||
"Cannot delete folder. It is not empty. "
|
||||
"Recursive deletion is not supported. "
|
||||
"Please delete the content first."
|
||||
@@ -579,7 +588,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
self.theParent.mainMenu.setAvailableRoot()
|
||||
self._setTreeChanged(True)
|
||||
else:
|
||||
self.makeAlert((
|
||||
self.makeAlert(self.tr(
|
||||
"Cannot delete root folder. It is not empty. "
|
||||
"Recursive deletion is not supported. "
|
||||
"Please delete the content first."
|
||||
@@ -835,7 +844,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
snItem = self.theProject.projTree[sHandle]
|
||||
dnItem = self.theProject.projTree[dHandle]
|
||||
if dnItem is None:
|
||||
self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR)
|
||||
self.makeAlert(self.tr("The item cannot be moved to that location."), nwAlert.ERROR)
|
||||
return
|
||||
|
||||
pItem = sItem.parent()
|
||||
@@ -866,7 +875,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
else:
|
||||
theEvent.ignore()
|
||||
logger.debug("Drag'n'drop of item %s not accepted" % sHandle)
|
||||
self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR)
|
||||
self.makeAlert(self.tr("The item cannot be moved to that location."), nwAlert.ERROR)
|
||||
|
||||
return
|
||||
|
||||
@@ -964,7 +973,9 @@ class GuiProjectTree(QTreeWidget):
|
||||
self.addTopLevelItem(newItem)
|
||||
else:
|
||||
self.makeAlert(
|
||||
"There is nowhere to add item with name '%s'" % 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
|
||||
@@ -1083,43 +1094,43 @@ class GuiProjectTreeMenu(QMenu):
|
||||
self.theTree = theTree
|
||||
self.theItem = None
|
||||
|
||||
self.editItem = QAction("Edit Project Item", self)
|
||||
self.editItem = QAction(self.tr("Edit Project Item"), self)
|
||||
self.editItem.triggered.connect(self._doEditItem)
|
||||
self.addAction(self.editItem)
|
||||
|
||||
self.openItem = QAction("Open Document", self)
|
||||
self.openItem = QAction(self.tr("Open Document"), self)
|
||||
self.openItem.triggered.connect(self._doOpenItem)
|
||||
self.addAction(self.openItem)
|
||||
|
||||
self.viewItem = QAction("View Document", self)
|
||||
self.viewItem = QAction(self.tr("View Document"), self)
|
||||
self.viewItem.triggered.connect(self._doViewItem)
|
||||
self.addAction(self.viewItem)
|
||||
|
||||
self.toggleExp = QAction("Toggle Included Flag", self)
|
||||
self.toggleExp = QAction(self.tr("Toggle Included Flag"), self)
|
||||
self.toggleExp.triggered.connect(self._doToggleExported)
|
||||
self.addAction(self.toggleExp)
|
||||
|
||||
self.newFile = QAction("New File", self)
|
||||
self.newFile = QAction(self.tr("New File"), self)
|
||||
self.newFile.triggered.connect(self._doMakeFile)
|
||||
self.addAction(self.newFile)
|
||||
|
||||
self.newFolder = QAction("New Folder", self)
|
||||
self.newFolder = QAction(self.tr("New Folder"), self)
|
||||
self.newFolder.triggered.connect(self._doMakeFolder)
|
||||
self.addAction(self.newFolder)
|
||||
|
||||
self.deleteItem = QAction("Delete Item", self)
|
||||
self.deleteItem = QAction(self.tr("Delete Item"), self)
|
||||
self.deleteItem.triggered.connect(self._doDeleteItem)
|
||||
self.addAction(self.deleteItem)
|
||||
|
||||
self.emptyTrash = QAction("Empty Trash", self)
|
||||
self.emptyTrash = QAction(self.tr("Empty Trash"), self)
|
||||
self.emptyTrash.triggered.connect(self._doEmptyTrash)
|
||||
self.addAction(self.emptyTrash)
|
||||
|
||||
self.moveUp = QAction("Move Item Up", self)
|
||||
self.moveUp = QAction(self.tr("Move Item Up"), self)
|
||||
self.moveUp.triggered.connect(self._doMoveUp)
|
||||
self.addAction(self.moveUp)
|
||||
|
||||
self.moveDown = QAction("Move Item Down", self)
|
||||
self.moveDown = QAction(self.tr("Move Item Down"), self)
|
||||
self.moveDown.triggered.connect(self._doMoveDown)
|
||||
self.addAction(self.moveDown)
|
||||
|
||||
|
||||
+60
-44
@@ -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__)
|
||||
@@ -94,16 +94,18 @@ class ProjWizardIntroPage(QWizardPage):
|
||||
self.theWizard = theWizard
|
||||
self.theTheme = theWizard.theTheme
|
||||
|
||||
self.setTitle("Create New Project")
|
||||
self.theText = QLabel(
|
||||
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.theText.setWordWrap(True)
|
||||
|
||||
self.imgCredit = QLabel("Side image by Peter Mitterhofer, CC BY-SA 4.0")
|
||||
self.imgCredit = QLabel(self.tr("Side image by {0}, {1}").format(
|
||||
"Peter Mitterhofer", "CC BY-SA 4.0"
|
||||
))
|
||||
lblFont = self.imgCredit.font()
|
||||
lblFont.setPointSizeF(0.6*self.theTheme.fontPointSize)
|
||||
self.imgCredit.setFont(lblFont)
|
||||
@@ -117,22 +119,22 @@ class ProjWizardIntroPage(QWizardPage):
|
||||
self.projName = QLineEdit()
|
||||
self.projName.setMaxLength(200)
|
||||
self.projName.setFixedWidth(xW)
|
||||
self.projName.setPlaceholderText("Required")
|
||||
self.projName.setPlaceholderText(self.tr("Required"))
|
||||
|
||||
self.projTitle = QLineEdit()
|
||||
self.projTitle.setMaxLength(200)
|
||||
self.projTitle.setFixedWidth(xW)
|
||||
self.projTitle.setPlaceholderText("Optional")
|
||||
self.projTitle.setPlaceholderText(self.tr("Optional"))
|
||||
|
||||
self.projAuthors = QPlainTextEdit()
|
||||
self.projAuthors.setFixedHeight(xH)
|
||||
self.projAuthors.setFixedWidth(xW)
|
||||
self.projAuthors.setPlaceholderText("Optional. One name per line.")
|
||||
self.projAuthors.setPlaceholderText(self.tr("Optional. One name per line."))
|
||||
|
||||
self.mainForm = QFormLayout()
|
||||
self.mainForm.addRow("Working Title", self.projName)
|
||||
self.mainForm.addRow("Novel Title", self.projTitle)
|
||||
self.mainForm.addRow("Author(s)", self.projAuthors)
|
||||
self.mainForm.addRow(self.tr("Working Title"), self.projName)
|
||||
self.mainForm.addRow(self.tr("Novel Title"), self.projTitle)
|
||||
self.mainForm.addRow(self.tr("Author(s)"), self.projAuthors)
|
||||
self.mainForm.setVerticalSpacing(fS)
|
||||
|
||||
self.registerField("projName*", self.projName)
|
||||
@@ -161,11 +163,11 @@ class ProjWizardFolderPage(QWizardPage):
|
||||
self.theWizard = theWizard
|
||||
self.theTheme = theWizard.theTheme
|
||||
|
||||
self.setTitle("Select Project Folder")
|
||||
self.theText = QLabel(
|
||||
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.theText.setWordWrap(True)
|
||||
|
||||
xW = self.mainConf.pxInt(300)
|
||||
@@ -174,14 +176,14 @@ class ProjWizardFolderPage(QWizardPage):
|
||||
|
||||
self.projPath = QLineEdit("")
|
||||
self.projPath.setFixedWidth(xW)
|
||||
self.projPath.setPlaceholderText("Required")
|
||||
self.projPath.setPlaceholderText(self.tr("Required"))
|
||||
|
||||
self.browseButton = QPushButton("...")
|
||||
self.browseButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("...")))
|
||||
self.browseButton.clicked.connect(self._doBrowse)
|
||||
|
||||
self.mainForm = QHBoxLayout()
|
||||
self.mainForm.addWidget(QLabel("Project Path"), 0)
|
||||
self.mainForm.addWidget(QLabel(self.tr("Project Path")), 0)
|
||||
self.mainForm.addWidget(self.projPath, 1)
|
||||
self.mainForm.addWidget(self.browseButton, 0)
|
||||
self.mainForm.setSpacing(fS)
|
||||
@@ -213,7 +215,7 @@ class ProjWizardFolderPage(QWizardPage):
|
||||
dlgOpt |= QFileDialog.ShowDirsOnly
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
projDir = QFileDialog.getExistingDirectory(
|
||||
self, "Select Project Folder", lastPath, options=dlgOpt
|
||||
self, self.tr("Select Project Folder"), lastPath, options=dlgOpt
|
||||
)
|
||||
if projDir:
|
||||
projName = self.field("projName")
|
||||
@@ -235,20 +237,20 @@ class ProjWizardPopulatePage(QWizardPage):
|
||||
self.mainConf = nw.CONFIG
|
||||
self.theWizard = theWizard
|
||||
|
||||
self.setTitle("Populate Project")
|
||||
self.theText = QLabel(
|
||||
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.theText.setWordWrap(True)
|
||||
|
||||
vS = self.mainConf.pxInt(12)
|
||||
fS = self.mainConf.pxInt(4)
|
||||
|
||||
self.popMinimal = QRadioButton("Fill the project with a minimal set of items")
|
||||
self.popSample = QRadioButton("Fill the project with example files")
|
||||
self.popCustom = QRadioButton("Show detailed options for filling the project")
|
||||
self.popMinimal = QRadioButton(self.tr("Fill the project with a minimal set of items"))
|
||||
self.popSample = QRadioButton(self.tr("Fill the project with example files"))
|
||||
self.popCustom = QRadioButton(self.tr("Show detailed options for filling the project"))
|
||||
self.popMinimal.setChecked(True)
|
||||
|
||||
self.popBox = QVBoxLayout()
|
||||
@@ -290,27 +292,39 @@ class ProjWizardCustomPage(QWizardPage):
|
||||
self.mainConf = nw.CONFIG
|
||||
self.theWizard = theWizard
|
||||
|
||||
self.setTitle("Custom Project Options")
|
||||
self.theText = QLabel(
|
||||
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.theText.setWordWrap(True)
|
||||
|
||||
vS = self.mainConf.pxInt(12)
|
||||
|
||||
# Root Folders
|
||||
self.rootGroup = QGroupBox("Additional Root Folders")
|
||||
self.rootGroup = QGroupBox(self.tr("Additional Root Folders"))
|
||||
self.rootForm = QGridLayout()
|
||||
self.rootGroup.setLayout(self.rootForm)
|
||||
|
||||
self.lblPlot = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.PLOT])
|
||||
self.lblChar = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.CHARACTER])
|
||||
self.lblWorld = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.WORLD])
|
||||
self.lblTime = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.TIMELINE])
|
||||
self.lblObject = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.OBJECT])
|
||||
self.lblEntity = QLabel("%s folder" % nwLabels.CLASS_NAME[nwItemClass.ENTITY])
|
||||
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(
|
||||
trConst(nwLabels.CLASS_NAME[nwItemClass.OBJECT]))
|
||||
)
|
||||
self.lblEntity = QLabel(self.tr("{0} folder").format(
|
||||
trConst(nwLabels.CLASS_NAME[nwItemClass.ENTITY]))
|
||||
)
|
||||
|
||||
self.addPlot = QSwitch()
|
||||
self.addChar = QSwitch()
|
||||
@@ -338,7 +352,7 @@ class ProjWizardCustomPage(QWizardPage):
|
||||
self.rootForm.setRowStretch(6, 1)
|
||||
|
||||
# Novel Options
|
||||
self.novelGroup = QGroupBox("Populate Novel Folder")
|
||||
self.novelGroup = QGroupBox(self.tr("Populate Novel Folder"))
|
||||
self.novelForm = QGridLayout()
|
||||
self.novelGroup.setLayout(self.novelForm)
|
||||
|
||||
@@ -353,9 +367,9 @@ class ProjWizardCustomPage(QWizardPage):
|
||||
self.chFolders = QSwitch()
|
||||
self.chFolders.setChecked(True)
|
||||
|
||||
self.novelForm.addWidget(QLabel("Add chapters"), 0, 0)
|
||||
self.novelForm.addWidget(QLabel("Scenes (per chapter)"), 1, 0)
|
||||
self.novelForm.addWidget(QLabel("Add chapter folders"), 2, 0)
|
||||
self.novelForm.addWidget(QLabel(self.tr("Add chapters")), 0, 0)
|
||||
self.novelForm.addWidget(QLabel(self.tr("Scenes (per chapter)")), 1, 0)
|
||||
self.novelForm.addWidget(QLabel(self.tr("Add chapter folders")), 2, 0)
|
||||
self.novelForm.addWidget(self.numChapters, 0, 1, 1, 1, Qt.AlignRight)
|
||||
self.novelForm.addWidget(self.numScenes, 1, 1, 1, 1, Qt.AlignRight)
|
||||
self.novelForm.addWidget(self.chFolders, 2, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -396,13 +410,15 @@ class ProjWizardFinalPage(QWizardPage):
|
||||
self.mainConf = nw.CONFIG
|
||||
self.theWizard = theWizard
|
||||
|
||||
self.setTitle("Finished")
|
||||
self.theText = QLabel((
|
||||
"<p>All done.</p>"
|
||||
"<p>Press '{finish}' to create the new project.</p>"
|
||||
).format(
|
||||
finish = "Done" if self.mainConf.osDarwin else "Finish"
|
||||
))
|
||||
self.setTitle(self.tr("Finished"))
|
||||
self.theText = QLabel(
|
||||
"<p>{done}</p><p>{help}</p>".format(
|
||||
done = self.tr("All done."),
|
||||
help = 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)
|
||||
|
||||
# Assemble
|
||||
|
||||
+16
-12
@@ -29,10 +29,10 @@ import logging
|
||||
|
||||
from time import time
|
||||
|
||||
from PyQt5.QtCore import QLocale
|
||||
from PyQt5.QtGui import QColor, QPainter
|
||||
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton
|
||||
|
||||
from nw.core import NWSpellCheck
|
||||
from nw.common import formatTime
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -63,7 +63,7 @@ class GuiMainStatus(QStatusBar):
|
||||
|
||||
## The Spell Checker Language
|
||||
self.langIcon = QLabel("")
|
||||
self.langText = QLabel("None")
|
||||
self.langText = QLabel(self.tr("None"))
|
||||
self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx)))
|
||||
self.langIcon.setContentsMargins(0, 0, 0, 0)
|
||||
self.langText.setContentsMargins(0, 0, xM, 0)
|
||||
@@ -72,7 +72,7 @@ class GuiMainStatus(QStatusBar):
|
||||
|
||||
## The Editor Status
|
||||
self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
|
||||
self.docText = QLabel("Editor")
|
||||
self.docText = QLabel(self.tr("Editor"))
|
||||
self.docIcon.setContentsMargins(0, 0, 0, 0)
|
||||
self.docText.setContentsMargins(0, 0, xM, 0)
|
||||
self.addPermanentWidget(self.docIcon)
|
||||
@@ -80,7 +80,7 @@ class GuiMainStatus(QStatusBar):
|
||||
|
||||
## The Project Status
|
||||
self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
|
||||
self.projText = QLabel("Project")
|
||||
self.projText = QLabel(self.tr("Project"))
|
||||
self.projIcon.setContentsMargins(0, 0, 0, 0)
|
||||
self.projText.setContentsMargins(0, 0, xM, 0)
|
||||
self.addPermanentWidget(self.projIcon)
|
||||
@@ -103,7 +103,7 @@ class GuiMainStatus(QStatusBar):
|
||||
self.timeIcon = QLabel()
|
||||
self.timeText = QLabel("")
|
||||
self.timeIcon.setPixmap(self.timePixmap)
|
||||
self.timeText.setToolTip("Session Time")
|
||||
self.timeText.setToolTip(self.tr("Session Time"))
|
||||
self.timeText.setMinimumWidth(self.theTheme.getTextWidth("00:00:00:"))
|
||||
self.timeIcon.setContentsMargins(0, 0, 0, 0)
|
||||
self.timeText.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -151,13 +151,17 @@ class GuiMainStatus(QStatusBar):
|
||||
"""Set the language code for the spell checker.
|
||||
"""
|
||||
if theLanguage is None:
|
||||
self.langText.setText("None")
|
||||
self.langText.setText(self.tr("None"))
|
||||
self.langText.setToolTip("")
|
||||
else:
|
||||
self.langText.setText(NWSpellCheck.expandLanguage(theLanguage))
|
||||
self.langText.setToolTip(
|
||||
"Provider: %s" % (theProvider if theProvider else "unknown")
|
||||
)
|
||||
qLocal = QLocale(theLanguage)
|
||||
spLang = qLocal.nativeLanguageName().title()
|
||||
self.langText.setText(spLang)
|
||||
if theProvider:
|
||||
self.langText.setToolTip("%s (%s)" % (theLanguage, theProvider))
|
||||
else:
|
||||
self.langText.setToolTip(theLanguage)
|
||||
|
||||
return
|
||||
|
||||
def setProjectStatus(self, isChanged):
|
||||
@@ -175,8 +179,8 @@ class GuiMainStatus(QStatusBar):
|
||||
def setStats(self, pWC, sWC):
|
||||
"""Set the current project statistics.
|
||||
"""
|
||||
self.statsText.setText(f"Words: {pWC:n} ({sWC:+n})")
|
||||
self.statsText.setToolTip("Project word count (session change)")
|
||||
self.statsText.setText(self.tr("Words: {0} ({1})").format(f"{pWC:n}", f"{sWC:+n}"))
|
||||
self.statsText.setToolTip(self.tr("Project word count (session change)"))
|
||||
return
|
||||
|
||||
def setUserIdle(self, userIdle):
|
||||
|
||||
+12
-7
@@ -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,8 +397,8 @@ class GuiTheme:
|
||||
with open(themeConf, mode="r", encoding="utf8") as inFile:
|
||||
confParser.read_file(inFile)
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Could not load theme config file.", str(e)], nwAlert.ERROR
|
||||
self.makeAlert(
|
||||
[self.tr("Could not load theme config file."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
continue
|
||||
themeName = ""
|
||||
@@ -425,8 +430,8 @@ class GuiTheme:
|
||||
with open(syntaxPath, mode="r", encoding="utf8") as inFile:
|
||||
confParser.read_file(inFile)
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Could not load syntax file.", str(e)], nwAlert.ERROR
|
||||
self.makeAlert(
|
||||
[self.tr("Could not load syntax file."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
return []
|
||||
syntaxName = ""
|
||||
@@ -740,8 +745,8 @@ class GuiIcons:
|
||||
with open(themeConf, mode="r", encoding="utf8") as inFile:
|
||||
confParser.read_file(inFile)
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Could not load theme config file.", str(e)], nwAlert.ERROR
|
||||
self.makeAlert(
|
||||
[self.tr("Could not load theme config file."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
continue
|
||||
themeName = ""
|
||||
|
||||
+9
-6
@@ -52,7 +52,7 @@ class GuiWordList(QDialog):
|
||||
self.theProject = theProject
|
||||
self.optState = theProject.optState
|
||||
|
||||
self.setWindowTitle("Project Word List")
|
||||
self.setWindowTitle(self.tr("Project Word List"))
|
||||
|
||||
mS = self.mainConf.pxInt(250)
|
||||
wW = self.mainConf.pxInt(320)
|
||||
@@ -68,7 +68,7 @@ class GuiWordList(QDialog):
|
||||
# Main Widgets
|
||||
# ============
|
||||
|
||||
self.headLabel = QLabel("<b>Project Word List</b>")
|
||||
self.headLabel = QLabel("<b>%s</b>" % self.tr("Project Word List"))
|
||||
|
||||
self.listBox = QListWidget()
|
||||
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
|
||||
@@ -77,11 +77,11 @@ class GuiWordList(QDialog):
|
||||
self.newEntry = QLineEdit()
|
||||
|
||||
self.addButton = QPushButton(self.theTheme.getIcon("add"), "")
|
||||
self.addButton.setToolTip("Add new entry")
|
||||
self.addButton.setToolTip(self.tr("Add new entry"))
|
||||
self.addButton.clicked.connect(self._doAdd)
|
||||
|
||||
self.delButton = QPushButton(self.theTheme.getIcon("remove"), "")
|
||||
self.delButton.setToolTip("Delete selected entry")
|
||||
self.delButton.setToolTip(self.tr("Delete selected entry"))
|
||||
self.delButton.clicked.connect(self._doDelete)
|
||||
|
||||
self.editBox = QHBoxLayout()
|
||||
@@ -90,6 +90,8 @@ class GuiWordList(QDialog):
|
||||
self.editBox.addWidget(self.delButton, 0)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close)
|
||||
self.buttonBox.button(QDialogButtonBox.Save).setText(self.tr("Save"))
|
||||
self.buttonBox.button(QDialogButtonBox.Close).setText(self.tr("Close"))
|
||||
self.buttonBox.accepted.connect(self._doSave)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
@@ -121,12 +123,13 @@ class GuiWordList(QDialog):
|
||||
"""
|
||||
newWord = self.newEntry.text().strip()
|
||||
if newWord == "":
|
||||
self.theParent.makeAlert("Cannot add a blank word.", nwAlert.ERROR)
|
||||
self.theParent.makeAlert(self.tr("Cannot add a blank word."), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
if self.listBox.findItems(newWord, Qt.MatchExactly):
|
||||
self.theParent.makeAlert(
|
||||
"The word '%s' is already in the word list." % newWord, nwAlert.ERROR
|
||||
self.tr("The word '{0}' is already in the word list.").format(newWord),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
+40
-24
@@ -72,7 +72,7 @@ class GuiWritingStats(QDialog):
|
||||
self.timeFilter = 0.0
|
||||
self.wordOffset = 0
|
||||
|
||||
self.setWindowTitle("Writing Statistics")
|
||||
self.setWindowTitle(self.tr("Writing Statistics"))
|
||||
self.setMinimumWidth(self.mainConf.pxInt(420))
|
||||
self.setMinimumHeight(self.mainConf.pxInt(400))
|
||||
self.resize(
|
||||
@@ -95,7 +95,13 @@ class GuiWritingStats(QDialog):
|
||||
)
|
||||
|
||||
self.listBox = QTreeWidget()
|
||||
self.listBox.setHeaderLabels(["Session Start", "Length", "Idle", "Words", "Histogram"])
|
||||
self.listBox.setHeaderLabels([
|
||||
self.tr("Session Start"),
|
||||
self.tr("Length"),
|
||||
self.tr("Idle"),
|
||||
self.tr("Words"),
|
||||
self.tr("Histogram"),
|
||||
])
|
||||
self.listBox.setIndentation(0)
|
||||
self.listBox.setColumnWidth(self.C_TIME, wCol0)
|
||||
self.listBox.setColumnWidth(self.C_LENGTH, wCol1)
|
||||
@@ -125,7 +131,7 @@ class GuiWritingStats(QDialog):
|
||||
self.barImage.fill(self.palette().highlight().color())
|
||||
|
||||
# Session Info
|
||||
self.infoBox = QGroupBox("Sum Totals", self)
|
||||
self.infoBox = QGroupBox(self.tr("Sum Totals"), self)
|
||||
self.infoForm = QGridLayout(self)
|
||||
self.infoBox.setLayout(self.infoForm)
|
||||
|
||||
@@ -153,24 +159,33 @@ class GuiWritingStats(QDialog):
|
||||
self.totalWords.setFont(self.theTheme.guiFontFixed)
|
||||
self.totalWords.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
|
||||
|
||||
self.infoForm.addWidget(QLabel("Total Time:"), 0, 0)
|
||||
self.infoForm.addWidget(QLabel("Idle Time:"), 1, 0)
|
||||
self.infoForm.addWidget(QLabel("Filtered Time:"), 2, 0)
|
||||
self.infoForm.addWidget(QLabel("Novel Word Count:"), 3, 0)
|
||||
self.infoForm.addWidget(QLabel("Notes Word Count:"), 4, 0)
|
||||
self.infoForm.addWidget(QLabel("Total Word Count:"), 5, 0)
|
||||
lblTTime = QLabel(self.tr("Total Time:"))
|
||||
lblITime = QLabel(self.tr("Idle Time:"))
|
||||
lblFTime = QLabel(self.tr("Filtered Time:"))
|
||||
lblNvCount = QLabel(self.tr("Novel Word Count:"))
|
||||
lblNtCount = QLabel(self.tr("Notes Word Count:"))
|
||||
lblTtCount = QLabel(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
|
||||
sPx = self.theTheme.baseIconSize
|
||||
|
||||
self.filterBox = QGroupBox("Filters", self)
|
||||
self.filterBox = QGroupBox(self.tr("Filters"), self)
|
||||
self.filterForm = QGridLayout(self)
|
||||
self.filterBox.setLayout(self.filterForm)
|
||||
|
||||
@@ -210,12 +225,12 @@ class GuiWritingStats(QDialog):
|
||||
)
|
||||
self.showIdleTime.clicked.connect(self._updateListBox)
|
||||
|
||||
self.filterForm.addWidget(QLabel("Count novel files"), 0, 0)
|
||||
self.filterForm.addWidget(QLabel("Count note files"), 1, 0)
|
||||
self.filterForm.addWidget(QLabel("Hide zero word count"), 2, 0)
|
||||
self.filterForm.addWidget(QLabel("Hide negative word count"), 3, 0)
|
||||
self.filterForm.addWidget(QLabel("Group entries by day"), 4, 0)
|
||||
self.filterForm.addWidget(QLabel("Show idle time"), 5, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Count novel files")), 0, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Count note files")), 1, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Hide zero word count")), 2, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Hide negative word count")), 3, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Group entries by day")), 4, 0)
|
||||
self.filterForm.addWidget(QLabel(self.tr("Show idle time")), 5, 0)
|
||||
self.filterForm.addWidget(self.incNovel, 0, 1)
|
||||
self.filterForm.addWidget(self.incNotes, 1, 1)
|
||||
self.filterForm.addWidget(self.hideZeros, 2, 1)
|
||||
@@ -236,7 +251,7 @@ class GuiWritingStats(QDialog):
|
||||
|
||||
self.optsBox = QHBoxLayout()
|
||||
self.optsBox.addStretch(1)
|
||||
self.optsBox.addWidget(QLabel("Word count cap for the histogram"), 0)
|
||||
self.optsBox.addWidget(QLabel(self.tr("Word count cap for the histogram")), 0)
|
||||
self.optsBox.addWidget(self.histMax, 0)
|
||||
|
||||
# Buttons
|
||||
@@ -244,19 +259,20 @@ class GuiWritingStats(QDialog):
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
self.btnClose = self.buttonBox.addButton(QDialogButtonBox.Close)
|
||||
self.buttonBox.button(QDialogButtonBox.Close).setText(self.tr("Close"))
|
||||
self.btnClose.setAutoDefault(False)
|
||||
|
||||
self.btnSave = self.buttonBox.addButton("Save As", QDialogButtonBox.ActionRole)
|
||||
self.btnSave = self.buttonBox.addButton(self.tr("Save As"), QDialogButtonBox.ActionRole)
|
||||
self.btnSave.setAutoDefault(False)
|
||||
|
||||
self.saveMenu = QMenu(self)
|
||||
self.btnSave.setMenu(self.saveMenu)
|
||||
|
||||
self.saveJSON = QAction("JSON Data File (.json)", self)
|
||||
self.saveJSON = QAction(self.tr("JSON Data File (.json)"), self)
|
||||
self.saveJSON.triggered.connect(lambda: self._saveData(self.FMT_JSON))
|
||||
self.saveMenu.addAction(self.saveJSON)
|
||||
|
||||
self.saveCSV = QAction("CSV Data File (.csv)", self)
|
||||
self.saveCSV = QAction(self.tr("CSV Data File (.csv)"), self)
|
||||
self.saveCSV.triggered.connect(lambda: self._saveData(self.FMT_CSV))
|
||||
self.saveMenu.addAction(self.saveCSV)
|
||||
|
||||
@@ -338,10 +354,10 @@ class GuiWritingStats(QDialog):
|
||||
|
||||
if dataFmt == self.FMT_JSON:
|
||||
fileExt = "json"
|
||||
textFmt = "JSON Data File"
|
||||
textFmt = self.tr("JSON Data File")
|
||||
elif dataFmt == self.FMT_CSV:
|
||||
fileExt = "csv"
|
||||
textFmt = "CSV Data File"
|
||||
textFmt = self.tr("CSV Data File")
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -356,7 +372,7 @@ class GuiWritingStats(QDialog):
|
||||
dlgOpt = QFileDialog.Options()
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
savePath, _ = QFileDialog.getSaveFileName(
|
||||
self, "Save Document As", savePath, options=dlgOpt
|
||||
self, self.tr("Save Document As"), savePath, options=dlgOpt
|
||||
)
|
||||
if not savePath:
|
||||
return False
|
||||
@@ -474,7 +490,7 @@ class GuiWritingStats(QDialog):
|
||||
|
||||
except Exception as e:
|
||||
self.theParent.makeAlert(
|
||||
["Failed to read session log file.", str(e)], nwAlert.ERROR
|
||||
[self.tr("Failed to read session log file."), str(e)], nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
+82
-55
@@ -76,6 +76,7 @@ class GuiMain(QMainWindow):
|
||||
logger.info("Python Version: %s (0x%x)" % (
|
||||
self.mainConf.verPyString, self.mainConf.verPyHexVal)
|
||||
)
|
||||
logger.info("GUI Language: %s" % self.mainConf.guiLang)
|
||||
|
||||
# Core Classes
|
||||
# ============
|
||||
@@ -122,8 +123,8 @@ class GuiMain(QMainWindow):
|
||||
self.projTabs = QTabWidget()
|
||||
self.projTabs.setTabPosition(QTabWidget.South)
|
||||
self.projTabs.setStyleSheet(r"QTabWidget::pane {border: 0;};")
|
||||
self.projTabs.addTab(self.treeView, "Project")
|
||||
self.projTabs.addTab(self.novelView, "Novel")
|
||||
self.projTabs.addTab(self.treeView, self.tr("Project"))
|
||||
self.projTabs.addTab(self.novelView, self.tr("Novel"))
|
||||
self.projTabs.currentChanged.connect(self._projTabsChanged)
|
||||
|
||||
tabFont = self.projTabs.tabBar().font()
|
||||
@@ -139,17 +140,17 @@ class GuiMain(QMainWindow):
|
||||
self.treeButtons.setStyleSheet(r"QToolBar {padding: 0;}")
|
||||
self.projTabs.setCornerWidget(self.treeButtons, Qt.BottomRightCorner)
|
||||
|
||||
self.projDetailsBtn = QAction("Project Details")
|
||||
self.projDetailsBtn = QAction(self.tr("Project Details"))
|
||||
self.projDetailsBtn.setIcon(self.theTheme.getIcon("status_lines"))
|
||||
self.projDetailsBtn.triggered.connect(lambda: self.showProjectDetailsDialog())
|
||||
self.treeButtons.addAction(self.projDetailsBtn)
|
||||
|
||||
self.projStatsBtn = QAction("Writing Statistics")
|
||||
self.projStatsBtn = QAction(self.tr("Writing Statistics"))
|
||||
self.projStatsBtn.setIcon(self.theTheme.getIcon("status_stats"))
|
||||
self.projStatsBtn.triggered.connect(lambda: self.showWritingStatsDialog())
|
||||
self.treeButtons.addAction(self.projStatsBtn)
|
||||
|
||||
self.projSettingsBtn = QAction("Project Settings")
|
||||
self.projSettingsBtn = QAction(self.tr("Project Settings"))
|
||||
self.projSettingsBtn.setIcon(self.theTheme.getIcon("settings"))
|
||||
self.projSettingsBtn.triggered.connect(lambda: self.showProjectSettingsDialog())
|
||||
self.treeButtons.addAction(self.projSettingsBtn)
|
||||
@@ -184,8 +185,8 @@ class GuiMain(QMainWindow):
|
||||
self.mainTabs = QTabWidget()
|
||||
self.mainTabs.setTabPosition(QTabWidget.East)
|
||||
self.mainTabs.setStyleSheet(r"QTabWidget::pane {border: 0;}")
|
||||
self.mainTabs.addTab(self.splitDocs, "Editor")
|
||||
self.mainTabs.addTab(self.splitOutline, "Outline")
|
||||
self.mainTabs.addTab(self.splitDocs, self.tr("Editor"))
|
||||
self.mainTabs.addTab(self.splitOutline, self.tr("Outline"))
|
||||
self.mainTabs.currentChanged.connect(self._mainTabChanged)
|
||||
|
||||
# Splitter : Project Tree / Main Tabs
|
||||
@@ -339,7 +340,7 @@ class GuiMain(QMainWindow):
|
||||
if self.hasProject:
|
||||
if not self.closeProject():
|
||||
self.makeAlert(
|
||||
"Cannot create new project when another project is open.",
|
||||
self.tr("Cannot create new project when another project is open."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
@@ -357,8 +358,10 @@ class GuiMain(QMainWindow):
|
||||
|
||||
if os.path.isfile(os.path.join(projPath, self.theProject.projFile)):
|
||||
self.makeAlert(
|
||||
"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
|
||||
|
||||
@@ -372,7 +375,7 @@ class GuiMain(QMainWindow):
|
||||
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||
self.statusBar.setProjectStatus(True)
|
||||
self.statusBar.setDocumentStatus(None)
|
||||
self.statusBar.setStatus("New project created ...")
|
||||
self.statusBar.setStatus(self.tr("New project created ..."))
|
||||
self._updateWindowTitle(self.theProject.projName)
|
||||
else:
|
||||
self.theProject.clearProject()
|
||||
@@ -391,8 +394,11 @@ class GuiMain(QMainWindow):
|
||||
|
||||
if not isYes:
|
||||
msgYes = self.askQuestion(
|
||||
"Close Project",
|
||||
"Close the current project?<br>Changes are saved automatically."
|
||||
self.tr("Close Project"),
|
||||
"%s<br>%s" % (
|
||||
self.tr("Close the current project?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
)
|
||||
)
|
||||
if not msgYes:
|
||||
return False
|
||||
@@ -407,7 +413,8 @@ class GuiMain(QMainWindow):
|
||||
doBackup = True
|
||||
if self.mainConf.askBeforeBackup:
|
||||
msgYes = self.askQuestion(
|
||||
"Backup Project", "Backup the current project?"
|
||||
self.tr("Backup Project"),
|
||||
self.tr("Backup the current project?")
|
||||
)
|
||||
if not msgYes:
|
||||
doBackup = False
|
||||
@@ -457,29 +464,35 @@ class GuiMain(QMainWindow):
|
||||
|
||||
try:
|
||||
lockDetails = (
|
||||
"<br><br>The project was locked by the computer "
|
||||
"'%s' (%s %s), last active on %s"
|
||||
) % (
|
||||
"<br>%s" % self.tr(
|
||||
"The project was locked by the computer "
|
||||
"'{0}' ({1} {2}), last active on {3}."
|
||||
)
|
||||
).format(
|
||||
self.theProject.lockedBy[0],
|
||||
self.theProject.lockedBy[1],
|
||||
self.theProject.lockedBy[2],
|
||||
datetime.fromtimestamp(
|
||||
int(self.theProject.lockedBy[3])
|
||||
).strftime("%x %X")
|
||||
datetime.fromtimestamp(int(self.theProject.lockedBy[3])).strftime("%x %X")
|
||||
)
|
||||
except Exception:
|
||||
lockDetails = ""
|
||||
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.warning(
|
||||
self, "Project Locked", (
|
||||
"The project is already open by another instance of novelWriter, and "
|
||||
"is therefore locked. Override lock and continue anyway?<br><br>"
|
||||
"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.%s"
|
||||
) % lockDetails,
|
||||
self, self.tr("Project Locked"),
|
||||
"%s<br><br>%s<br>%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."
|
||||
),
|
||||
lockDetails
|
||||
),
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
if msgRes == QMessageBox.Yes:
|
||||
@@ -514,6 +527,10 @@ class GuiMain(QMainWindow):
|
||||
|
||||
# Check if we need to rebuild the index
|
||||
if self.theIndex.indexBroken:
|
||||
self.makeAlert(
|
||||
self.tr("The project index is outdated or broken. Rebuilding index."),
|
||||
nwAlert.WARN
|
||||
)
|
||||
self.rebuildIndex()
|
||||
|
||||
# Make sure the changed status is set to false on all that was
|
||||
@@ -685,15 +702,16 @@ class GuiMain(QMainWindow):
|
||||
|
||||
lastPath = self.mainConf.lastPath
|
||||
extFilter = [
|
||||
"Text files (*.txt)",
|
||||
"Markdown files (*.md)",
|
||||
"novelWriter files (*.nwd)",
|
||||
"All files (*.*)",
|
||||
self.tr("Text files ({0})").format("*.txt"),
|
||||
self.tr("Markdown files ({0})").format("*.md"),
|
||||
self.tr("novelWriter files ({0})").format("*.nwd"),
|
||||
self.tr("All files ({0})").format("*.*"),
|
||||
]
|
||||
dlgOpt = QFileDialog.Options()
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
loadFile, _ = QFileDialog.getOpenFileName(
|
||||
self, "Import File", lastPath, options=dlgOpt, filter=";;".join(extFilter)
|
||||
self, self.tr("Import File"), lastPath,
|
||||
options=dlgOpt, filter=";;".join(extFilter)
|
||||
)
|
||||
if not loadFile:
|
||||
return False
|
||||
@@ -707,24 +725,26 @@ class GuiMain(QMainWindow):
|
||||
theText = inFile.read()
|
||||
self.mainConf.setLastPath(loadFile)
|
||||
except Exception as e:
|
||||
self.makeAlert(
|
||||
["Could not read file. The file must be an existing text file.", str(e)],
|
||||
nwAlert.ERROR
|
||||
)
|
||||
self.makeAlert([
|
||||
self.tr("Could not read file. The file must be an existing text file."), str(e)
|
||||
], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
if self.docEditor.theHandle is None:
|
||||
self.makeAlert(
|
||||
"Please open a document to import the text file into.",
|
||||
self.tr("Please open a document to import the text file into."),
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
if not self.docEditor.isEmpty():
|
||||
msgYes = self.askQuestion("Import Document", (
|
||||
"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
|
||||
|
||||
@@ -861,9 +881,9 @@ class GuiMain(QMainWindow):
|
||||
for nDone, tItem in enumerate(self.theProject.projTree):
|
||||
|
||||
if tItem is not None:
|
||||
self.setStatus("Indexing: '%s'" % tItem.itemName)
|
||||
self.setStatus(self.tr("Indexing: '{0}'").format(tItem.itemName))
|
||||
else:
|
||||
self.setStatus("Indexing: Unknown item")
|
||||
self.setStatus(self.tr("Indexing: '{0}'").format(self.tr("Unknown item")))
|
||||
|
||||
if tItem is not None and tItem.itemType == nwItemType.FILE:
|
||||
logger.verbose("Scanning: %s" % tItem.itemName)
|
||||
@@ -881,12 +901,16 @@ class GuiMain(QMainWindow):
|
||||
self.treeView.projectWordCount()
|
||||
|
||||
tEnd = time()
|
||||
self.setStatus("Indexing completed in %.1f ms" % ((tEnd - tStart)*1000.0))
|
||||
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("The project index has been successfully rebuilt.", nwAlert.INFO)
|
||||
self.makeAlert(
|
||||
self.tr("The project index has been successfully rebuilt."), nwAlert.INFO
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@@ -914,7 +938,7 @@ class GuiMain(QMainWindow):
|
||||
dlgOpt |= QFileDialog.ShowDirsOnly
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
projPath = QFileDialog.getExistingDirectory(
|
||||
self, "Save novelWriter Project", "", options=dlgOpt
|
||||
self, self.tr("Save novelWriter Project"), "", options=dlgOpt
|
||||
)
|
||||
if projPath:
|
||||
return projPath
|
||||
@@ -1100,14 +1124,14 @@ class GuiMain(QMainWindow):
|
||||
# Popup
|
||||
msgBox = QMessageBox()
|
||||
if theLevel == nwAlert.INFO:
|
||||
msgBox.information(self, "Information", popMsg)
|
||||
msgBox.information(self, self.tr("Information"), popMsg)
|
||||
elif theLevel == nwAlert.WARN:
|
||||
msgBox.warning(self, "Warning", popMsg)
|
||||
msgBox.warning(self, self.tr("Warning"), popMsg)
|
||||
elif theLevel == nwAlert.ERROR:
|
||||
msgBox.critical(self, "Error", popMsg)
|
||||
msgBox.critical(self, self.tr("Error"), popMsg)
|
||||
elif theLevel == nwAlert.BUG:
|
||||
popMsg += "<br>This is a bug!"
|
||||
msgBox.critical(self, "Internal Error", popMsg)
|
||||
popMsg += "<br>%s" % self.tr("This is a bug!")
|
||||
msgBox.critical(self, self.tr("Internal Error"), popMsg)
|
||||
|
||||
return
|
||||
|
||||
@@ -1115,7 +1139,7 @@ class GuiMain(QMainWindow):
|
||||
"""Ask the user a Yes/No question.
|
||||
"""
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(self, theTitle, theQuestion)
|
||||
msgRes = msgBox.question(self, theTitle, theQuestion, QMessageBox.Yes | QMessageBox.No)
|
||||
return msgRes == QMessageBox.Yes
|
||||
|
||||
def reportConfErr(self):
|
||||
@@ -1137,8 +1161,11 @@ class GuiMain(QMainWindow):
|
||||
"""
|
||||
if self.hasProject:
|
||||
msgYes = self.askQuestion(
|
||||
"Exit",
|
||||
"Do you want to exit novelWriter?<br>Changes are saved automatically."
|
||||
self.tr("Exit"),
|
||||
"%s<br>%s" % (
|
||||
self.tr("Do you want to exit novelWriter?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
)
|
||||
)
|
||||
if not msgYes:
|
||||
return False
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="1.2b1" hexVersion="0x010200b1" fileVersion="1.2" timeStamp="2021-02-11 17:04:25">
|
||||
<novelWriterXML appVersion="1.3a0" hexVersion="0x010300a0" fileVersion="1.2" timeStamp="2021-02-15 17:51:17">
|
||||
<project>
|
||||
<name>Sample Project</name>
|
||||
<title>Sample Project</title>
|
||||
<author>Jane Smith</author>
|
||||
<author>Jay Doh</author>
|
||||
<saveCount>936</saveCount>
|
||||
<saveCount>1021</saveCount>
|
||||
<autoCount>161</autoCount>
|
||||
<editTime>46791</editTime>
|
||||
<editTime>48283</editTime>
|
||||
</project>
|
||||
<settings>
|
||||
<doBackup>False</doBackup>
|
||||
@@ -120,7 +120,7 @@
|
||||
<charCount>1810</charCount>
|
||||
<wordCount>318</wordCount>
|
||||
<paraCount>8</paraCount>
|
||||
<cursorPos>3</cursorPos>
|
||||
<cursorPos>1112</cursorPos>
|
||||
</item>
|
||||
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
|
||||
<name>Another Scene</name>
|
||||
|
||||
@@ -186,6 +186,32 @@ def buildQtDocs():
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Qt Linguist QM Builder (qtlrelease)
|
||||
##
|
||||
|
||||
def buildQtI18n():
|
||||
"""Build the lang.qm files for Qt Linguist.
|
||||
"""
|
||||
try:
|
||||
subprocess.call(["lrelease", "-verbose", "novelWriter.pro"])
|
||||
except Exception as e:
|
||||
print("QtI18n Release Error:")
|
||||
print(str(e))
|
||||
|
||||
##
|
||||
# Qt Linguist TS Builder (qtlupdate)
|
||||
##
|
||||
|
||||
def buildQtI18nTS():
|
||||
"""Build the lang.ts files for Qt Linguist.
|
||||
"""
|
||||
try:
|
||||
subprocess.call(["pylupdate5", "-verbose", "-noobsolete", "novelWriter.pro"])
|
||||
except Exception as e:
|
||||
print("QtI18n Release Error:")
|
||||
print(str(e))
|
||||
|
||||
##
|
||||
# Sample Project ZIP File Builder (sample)
|
||||
##
|
||||
@@ -849,6 +875,8 @@ if __name__ == "__main__":
|
||||
"\n"
|
||||
" qthelp Build the help documentation for use with the Qt Assistant. Run before\n"
|
||||
" install to have local help enable in the the installed version.\n"
|
||||
" qtlupdate Update the translation files for internationalisation.\n"
|
||||
" qtlrelease Build the language files for internationalisation.\n"
|
||||
" sample Build the sample project as a zip file. Run before install to enable\n"
|
||||
" creating sample projects in the in-app New Project Wizard.\n"
|
||||
"\n"
|
||||
@@ -898,6 +926,14 @@ if __name__ == "__main__":
|
||||
sys.argv.remove("qthelp")
|
||||
buildQtDocs()
|
||||
|
||||
if "qtlrelease" in sys.argv:
|
||||
sys.argv.remove("qtlrelease")
|
||||
buildQtI18n()
|
||||
|
||||
if "qtlupdate" in sys.argv:
|
||||
sys.argv.remove("qtlupdate")
|
||||
buildQtI18nTS()
|
||||
|
||||
if "sample" in sys.argv:
|
||||
sys.argv.remove("sample")
|
||||
buildSampleZip()
|
||||
|
||||
@@ -25,6 +25,10 @@ To target the command, add one of `--target-linux`, `--target-darwin` or
|
||||
`qthelp` – Build the help documentation for use with the Qt Assistant. Run
|
||||
before install to have local help enable in the the installed version
|
||||
|
||||
`qtlupdate` – Update the translation files for internationalisation.
|
||||
|
||||
`qtlrelease` – Build the language files for internationalisation.
|
||||
|
||||
`sample` – Build the sample project as a zip file. Run before install to enable
|
||||
creating sample projects in the in-app New Project Wizard.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[Main]
|
||||
timestamp = 2021-02-09 21:07:03
|
||||
timestamp = 2021-02-15 16:31:24
|
||||
theme = default
|
||||
syntax = default_light
|
||||
icons = typicons_colour_light
|
||||
@@ -7,6 +7,7 @@ guidark = False
|
||||
guifont =
|
||||
guifontsize = 11
|
||||
lastnotes = 0x0
|
||||
guilang = en-GB
|
||||
|
||||
[Sizes]
|
||||
geometry = 1200, 650
|
||||
|
||||
@@ -7,6 +7,7 @@ guidark = True
|
||||
guifont = Sans
|
||||
guifontsize = 12
|
||||
lastnotes = 0x0
|
||||
guilang = en-GB
|
||||
|
||||
[Sizes]
|
||||
geometry = 1200, 650
|
||||
|
||||
@@ -145,7 +145,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir):
|
||||
assert os.path.isfile(confFile)
|
||||
|
||||
copyfile(confFile, testFile)
|
||||
assert cmpFiles(testFile, compFile, [2, 9])
|
||||
assert cmpFiles(testFile, compFile, [2, 9, 10])
|
||||
monkeypatch.undo()
|
||||
|
||||
# Load and save with OSError
|
||||
@@ -193,7 +193,7 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir):
|
||||
assert tstConf.saveConfig()
|
||||
|
||||
copyfile(confFile, testFile)
|
||||
assert cmpFiles(testFile, compFile, [2, 9])
|
||||
assert cmpFiles(testFile, compFile, [2, 9, 10])
|
||||
|
||||
# END Test testBaseConfig_Init
|
||||
|
||||
@@ -458,7 +458,7 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir):
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
copyfile(confFile, testFile)
|
||||
assert cmpFiles(testFile, compFile, [2, 9])
|
||||
assert cmpFiles(testFile, compFile, [2, 9, 10])
|
||||
|
||||
# END Test testBaseConfig_SettersGetters
|
||||
|
||||
|
||||
@@ -928,7 +928,7 @@ def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum):
|
||||
# First Item with Meta Data
|
||||
orphPath = os.path.join(nwLipsum, "content", "636b6aa9b697b.nwd")
|
||||
with open(orphPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write("%%~name:Mars\n")
|
||||
outFile.write("%%~name:[Recovered] Mars\n")
|
||||
outFile.write("%%~path:5eaea4e8cdee8/636b6aa9b697b\n")
|
||||
outFile.write("%%~kind:WORLD/NOTE\n")
|
||||
outFile.write("%%~invalid\n")
|
||||
@@ -962,7 +962,7 @@ def testCoreProject_OrphanedFiles(dummyGUI, nwLipsum):
|
||||
# First Item with Meta Data
|
||||
oItem = theProject.projTree["636b6aa9b697b"]
|
||||
assert oItem is not None
|
||||
assert oItem.itemName == "Recovered: Mars"
|
||||
assert oItem.itemName == "[Recovered] Mars"
|
||||
assert oItem.itemHandle == "636b6aa9b697b"
|
||||
assert oItem.itemParent == "60bdf227455cc"
|
||||
assert oItem.itemClass == nwItemClass.WORLD
|
||||
|
||||
@@ -28,7 +28,6 @@ from dummy import causeOSError
|
||||
from tools import readFile, writeFile
|
||||
|
||||
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
|
||||
from nw.constants import nwConst
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreSpell_Super(monkeypatch, tmpDir, tmpConf):
|
||||
@@ -48,10 +47,6 @@ def testCoreSpell_Super(monkeypatch, tmpDir, tmpConf):
|
||||
assert spChk.listDictionaries() == []
|
||||
assert spChk.describeDict() == ("", "")
|
||||
|
||||
# Check language info
|
||||
assert NWSpellCheck.expandLanguage("en") == "English"
|
||||
assert NWSpellCheck.expandLanguage("en_GB") == "English (GB)"
|
||||
|
||||
# Add a word to the user's dictionary
|
||||
assert spChk._readProjectDictionary("dummy") is False
|
||||
monkeypatch.setattr("builtins.open", causeOSError)
|
||||
@@ -178,11 +173,11 @@ def testCoreSpell_Simple(monkeypatch, tmpDir, tmpConf):
|
||||
assert "D_word" in wSuggest
|
||||
|
||||
# List dictionaries
|
||||
assert spChk.listDictionaries() == [("en", "English [%s]" % nwConst.SP_INTERNAL)]
|
||||
assert spChk.listDictionaries() == [("en", "difflib")]
|
||||
|
||||
# Description
|
||||
aTag, aName = spChk.describeDict()
|
||||
assert aTag == "en"
|
||||
assert aName == nwConst.SP_INTERNAL
|
||||
assert aName == ""
|
||||
|
||||
# END Test testCoreSpell_Simple
|
||||
|
||||
@@ -86,6 +86,7 @@ def testCoreTools_RomanNumbers():
|
||||
def testCoreTools_NumberWords():
|
||||
"""Test the conversion of integer to English words.
|
||||
"""
|
||||
# English
|
||||
assert numberToWord(0, "en") == "Zero"
|
||||
assert numberToWord(1, "en") == "One"
|
||||
assert numberToWord(2, "en") == "Two"
|
||||
@@ -114,14 +115,46 @@ def testCoreTools_NumberWords():
|
||||
assert numberToWord(142, "en") == "One Hundred Forty-Two"
|
||||
assert numberToWord(999, "en") == "Nine Hundred Ninety-Nine"
|
||||
|
||||
# Norwegian
|
||||
assert numberToWord(0, "nb") == "null"
|
||||
assert numberToWord(1, "nb") == "én"
|
||||
assert numberToWord(10, "nb") == "ti"
|
||||
assert numberToWord(20, "nb") == "tjue"
|
||||
assert numberToWord(21, "nb") == "tjueén"
|
||||
assert numberToWord(29, "nb") == "tjueni"
|
||||
assert numberToWord(42, "nb") == "førtito"
|
||||
assert numberToWord(60, "nb") == "seksti"
|
||||
assert numberToWord(100, "nb") == "ett hundre"
|
||||
assert numberToWord(114, "nb") == "ett hundre og fjorten"
|
||||
assert numberToWord(142, "nb") == "ett hundre og førtito"
|
||||
assert numberToWord(999, "nb") == "ni hundre og nittini"
|
||||
|
||||
assert numberToWord(0, "nn") == "null"
|
||||
assert numberToWord(1, "nn") == "ein"
|
||||
assert numberToWord(10, "nn") == "ti"
|
||||
assert numberToWord(20, "nn") == "tjue"
|
||||
assert numberToWord(21, "nn") == "tjueein"
|
||||
assert numberToWord(29, "nn") == "tjueni"
|
||||
assert numberToWord(42, "nn") == "førtito"
|
||||
assert numberToWord(60, "nn") == "seksti"
|
||||
assert numberToWord(100, "nn") == "eitt hundre"
|
||||
assert numberToWord(114, "nn") == "eitt hundre og fjorten"
|
||||
assert numberToWord(142, "nn") == "eitt hundre og førtito"
|
||||
assert numberToWord(999, "nn") == "ni hundre og nittini"
|
||||
|
||||
# Check complex language setting
|
||||
assert numberToWord(1, "en_GB") == "One"
|
||||
assert numberToWord(2, "en_GB") == "Two"
|
||||
assert numberToWord(3, "en_GB") == "Three"
|
||||
|
||||
# Check a few with a nonsense language setting
|
||||
assert numberToWord(1, "foo") == "One"
|
||||
assert numberToWord(2, "foo") == "Two"
|
||||
assert numberToWord(3, "foo") == "Three"
|
||||
assert numberToWord(1, "foo") == "1"
|
||||
assert numberToWord(2, "foo") == "2"
|
||||
assert numberToWord(3, "foo") == "3"
|
||||
|
||||
# Test out of range values
|
||||
assert numberToWord(12345, "en") == "[Out of Range]"
|
||||
assert numberToWord(-2345, "en") == "[Negative]"
|
||||
assert numberToWord(12345, "en") == "[>999]"
|
||||
assert numberToWord(-2345, "en") == "[<0]"
|
||||
assert numberToWord("234", "en") == "[NaN]"
|
||||
|
||||
# END Test testCoreTools_NumberWords
|
||||
|
||||
@@ -595,10 +595,9 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
|
||||
nwGUI.mainMenu.aFileDetails.activate(QAction.Trigger)
|
||||
|
||||
theBits = theMessage.split("<br>")
|
||||
assert len(theBits) == 3
|
||||
assert theBits[0] == "File details for the currently open file"
|
||||
assert theBits[1] == "Handle: 0e17daca5f3e1"
|
||||
assert theBits[2] == "Location: %s" % os.path.join(fncProj, "content", "0e17daca5f3e1.nwd")
|
||||
assert len(theBits) == 2
|
||||
assert theBits[0] == "The currently open file is saved in:"
|
||||
assert theBits[1] == os.path.join(fncProj, "content", "0e17daca5f3e1.nwd")
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
|
||||
@@ -245,13 +245,7 @@ def testGuiPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
|
||||
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf")
|
||||
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf")
|
||||
copyfile(projFile, testFile)
|
||||
ignoreLines = [
|
||||
2, # Timestamp
|
||||
9, # Release Notes
|
||||
12, 13, 14, 15, # Window sizes
|
||||
16, 17, 18, 19, # Window sizes
|
||||
7, 29, # Fonts (depends on system default)
|
||||
]
|
||||
ignoreLines = [2, 9, 10, 13, 14, 15, 16, 17, 18, 19, 20, 7, 30, 31]
|
||||
assert cmpFiles(testFile, compFile, ignoreLines)
|
||||
|
||||
# Clean up
|
||||
|
||||
Reference in New Issue
Block a user