novelWriter 2.6b2__py3-none-any.whl → 2.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/METADATA +2 -2
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/RECORD +107 -106
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +4 -4
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +2 -0
- novelwriter/assets/i18n/project_en_US.json +2 -0
- novelwriter/assets/i18n/project_es_419.json +2 -0
- novelwriter/assets/i18n/project_fr_FR.json +3 -1
- novelwriter/assets/i18n/project_it_IT.json +2 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -0
- novelwriter/assets/i18n/project_nb_NO.json +2 -0
- novelwriter/assets/i18n/project_nl_NL.json +2 -0
- novelwriter/assets/i18n/project_pl_PL.json +2 -0
- novelwriter/assets/i18n/project_pt_BR.json +2 -0
- novelwriter/assets/i18n/project_zh_CN.json +2 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/manual_fr_FR.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/common.py +1 -1
- novelwriter/config.py +45 -20
- novelwriter/constants.py +40 -36
- novelwriter/core/buildsettings.py +8 -1
- novelwriter/core/coretools.py +1 -1
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +1 -1
- novelwriter/core/item.py +1 -1
- novelwriter/core/itemmodel.py +1 -1
- novelwriter/core/options.py +1 -1
- novelwriter/core/project.py +3 -7
- novelwriter/core/projectdata.py +8 -2
- novelwriter/core/projectxml.py +1 -1
- novelwriter/core/sessions.py +1 -1
- novelwriter/core/spellcheck.py +1 -1
- novelwriter/core/status.py +17 -3
- novelwriter/core/storage.py +1 -1
- novelwriter/core/tree.py +1 -1
- novelwriter/dialogs/about.py +1 -1
- novelwriter/dialogs/docmerge.py +1 -1
- novelwriter/dialogs/docsplit.py +1 -1
- novelwriter/dialogs/editlabel.py +1 -1
- novelwriter/dialogs/preferences.py +16 -7
- novelwriter/dialogs/projectsettings.py +146 -96
- novelwriter/dialogs/quotes.py +1 -1
- novelwriter/dialogs/wordlist.py +11 -10
- novelwriter/enum.py +1 -8
- novelwriter/error.py +2 -2
- novelwriter/extensions/configlayout.py +1 -1
- novelwriter/extensions/eventfilters.py +1 -1
- novelwriter/extensions/modified.py +17 -5
- novelwriter/extensions/novelselector.py +4 -3
- novelwriter/extensions/pagedsidebar.py +4 -4
- novelwriter/extensions/progressbars.py +4 -4
- novelwriter/extensions/statusled.py +8 -9
- novelwriter/extensions/switch.py +3 -3
- novelwriter/extensions/switchbox.py +1 -1
- novelwriter/extensions/versioninfo.py +1 -1
- novelwriter/formats/shared.py +13 -12
- novelwriter/formats/todocx.py +2 -2
- novelwriter/formats/tohtml.py +31 -28
- novelwriter/formats/tokenizer.py +19 -13
- novelwriter/formats/tomarkdown.py +4 -3
- novelwriter/formats/toodt.py +2 -2
- novelwriter/formats/toqdoc.py +3 -1
- novelwriter/formats/toraw.py +1 -1
- novelwriter/gui/doceditor.py +39 -21
- novelwriter/gui/dochighlight.py +1 -1
- novelwriter/gui/docviewer.py +2 -2
- novelwriter/gui/docviewerpanel.py +1 -1
- novelwriter/gui/editordocument.py +1 -1
- novelwriter/gui/itemdetails.py +4 -3
- novelwriter/gui/mainmenu.py +1 -1
- novelwriter/gui/noveltree.py +1 -1
- novelwriter/gui/outline.py +8 -9
- novelwriter/gui/projtree.py +20 -25
- novelwriter/gui/search.py +2 -9
- novelwriter/gui/sidebar.py +1 -1
- novelwriter/gui/statusbar.py +26 -10
- novelwriter/gui/theme.py +1 -1
- novelwriter/guimain.py +2 -6
- novelwriter/shared.py +1 -1
- novelwriter/text/counting.py +1 -1
- novelwriter/text/patterns.py +1 -1
- novelwriter/tools/dictionaries.py +3 -3
- novelwriter/tools/lipsum.py +1 -1
- novelwriter/tools/manusbuild.py +1 -1
- novelwriter/tools/manuscript.py +7 -7
- novelwriter/tools/manussettings.py +9 -9
- novelwriter/tools/noveldetails.py +1 -1
- novelwriter/tools/welcome.py +2 -2
- novelwriter/tools/writingstats.py +1 -1
- novelwriter/types.py +2 -2
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/top_level.txt +0 -0
novelwriter/config.py
CHANGED
@@ -8,7 +8,7 @@ Created: 2022-11-09 [2.0rc2] RecentProjects
|
|
8
8
|
Created: 2024-06-16 [2.5rc1] RecentPaths
|
9
9
|
|
10
10
|
This file is a part of novelWriter
|
11
|
-
Copyright 2018
|
11
|
+
Copyright (C) 2018 Veronica Berglyd Olsen and novelWriter contributors
|
12
12
|
|
13
13
|
This program is free software: you can redistribute it and/or modify
|
14
14
|
it under the terms of the GNU General Public License as published by
|
@@ -32,6 +32,7 @@ import sys
|
|
32
32
|
from datetime import datetime
|
33
33
|
from pathlib import Path
|
34
34
|
from time import time
|
35
|
+
from typing import TYPE_CHECKING
|
35
36
|
|
36
37
|
from PyQt5.QtCore import (
|
37
38
|
PYQT_VERSION, PYQT_VERSION_STR, QT_VERSION, QT_VERSION_STR, QLibraryInfo,
|
@@ -47,6 +48,9 @@ from novelwriter.common import (
|
|
47
48
|
from novelwriter.constants import nwFiles, nwUnicode
|
48
49
|
from novelwriter.error import formatException, logException
|
49
50
|
|
51
|
+
if TYPE_CHECKING: # pragma: no cover
|
52
|
+
from novelwriter.core.projectdata import NWProjectData
|
53
|
+
|
50
54
|
logger = logging.getLogger(__name__)
|
51
55
|
|
52
56
|
|
@@ -101,8 +105,11 @@ class Config:
|
|
101
105
|
self._qtTrans = {}
|
102
106
|
|
103
107
|
# PDF Manual
|
104
|
-
|
105
|
-
self.
|
108
|
+
self._manuals: dict[str, Path] = {}
|
109
|
+
if (assets := self._appPath / "assets").is_dir():
|
110
|
+
for item in assets.iterdir():
|
111
|
+
if item.is_file() and item.stem.startswith("manual") and item.suffix == ".pdf":
|
112
|
+
self._manuals[item.stem] = item
|
106
113
|
|
107
114
|
# User Settings
|
108
115
|
# =============
|
@@ -112,7 +119,7 @@ class Config:
|
|
112
119
|
|
113
120
|
# General GUI Settings
|
114
121
|
self.guiLocale = self._qLocale.name()
|
115
|
-
self.guiTheme = "
|
122
|
+
self.guiTheme = "default_light" # GUI theme
|
116
123
|
self.guiSyntax = "default_light" # Syntax theme
|
117
124
|
self.guiFont = QFont() # Main GUI font
|
118
125
|
self.guiScale = 1.0 # Set automatically by Theme class
|
@@ -135,6 +142,7 @@ class Config:
|
|
135
142
|
self.emphLabels = True # Add emphasis to H1 and H2 item labels
|
136
143
|
self.backupOnClose = False # Flag for running automatic backups
|
137
144
|
self.askBeforeBackup = True # Flag for asking before running automatic backup
|
145
|
+
self.askBeforeExit = True # Flag for asking before exiting the app
|
138
146
|
|
139
147
|
# Text Editor Settings
|
140
148
|
self.textFont = QFont() # Editor font
|
@@ -194,6 +202,7 @@ class Config:
|
|
194
202
|
# State
|
195
203
|
self.showViewerPanel = True # The panel for the viewer is visible
|
196
204
|
self.showEditToolBar = False # The document editor toolbar visibility
|
205
|
+
self.showSessionTime = True # Show the session time in the status bar
|
197
206
|
self.viewComments = True # Comments are shown in the viewer
|
198
207
|
self.viewSynopsis = True # Synopsis is shown in the viewer
|
199
208
|
|
@@ -256,6 +265,10 @@ class Config:
|
|
256
265
|
def hasError(self) -> bool:
|
257
266
|
return self._hasError
|
258
267
|
|
268
|
+
@property
|
269
|
+
def pdfDocs(self) -> Path | None:
|
270
|
+
return self._manuals.get(f"manual_{self.locale.name()}", self._manuals.get("manual"))
|
271
|
+
|
259
272
|
@property
|
260
273
|
def locale(self) -> QLocale:
|
261
274
|
return self._dLocale
|
@@ -627,6 +640,7 @@ class Config:
|
|
627
640
|
self._backupPath = conf.rdPath(sec, "backuppath", self._backupPath)
|
628
641
|
self.backupOnClose = conf.rdBool(sec, "backuponclose", self.backupOnClose)
|
629
642
|
self.askBeforeBackup = conf.rdBool(sec, "askbeforebackup", self.askBeforeBackup)
|
643
|
+
self.askBeforeExit = conf.rdBool(sec, "askbeforeexit", self.askBeforeExit)
|
630
644
|
|
631
645
|
# Editor
|
632
646
|
sec = "Editor"
|
@@ -674,6 +688,7 @@ class Config:
|
|
674
688
|
sec = "State"
|
675
689
|
self.showViewerPanel = conf.rdBool(sec, "showviewerpanel", self.showViewerPanel)
|
676
690
|
self.showEditToolBar = conf.rdBool(sec, "showedittoolbar", self.showEditToolBar)
|
691
|
+
self.showSessionTime = conf.rdBool(sec, "showsessiontime", self.showSessionTime)
|
677
692
|
self.viewComments = conf.rdBool(sec, "viewcomments", self.viewComments)
|
678
693
|
self.viewSynopsis = conf.rdBool(sec, "viewsynopsis", self.viewSynopsis)
|
679
694
|
self.searchCase = conf.rdBool(sec, "searchcase", self.searchCase)
|
@@ -737,6 +752,7 @@ class Config:
|
|
737
752
|
"backuppath": str(self._backupPath),
|
738
753
|
"backuponclose": str(self.backupOnClose),
|
739
754
|
"askbeforebackup": str(self.askBeforeBackup),
|
755
|
+
"askbeforeexit": str(self.askBeforeExit),
|
740
756
|
}
|
741
757
|
|
742
758
|
conf["Editor"] = {
|
@@ -784,6 +800,7 @@ class Config:
|
|
784
800
|
conf["State"] = {
|
785
801
|
"showviewerpanel": str(self.showViewerPanel),
|
786
802
|
"showedittoolbar": str(self.showEditToolBar),
|
803
|
+
"showsessiontime": str(self.showSessionTime),
|
787
804
|
"viewcomments": str(self.viewComments),
|
788
805
|
"viewsynopsis": str(self.viewSynopsis),
|
789
806
|
"searchcase": str(self.searchCase),
|
@@ -839,29 +856,30 @@ class RecentProjects:
|
|
839
856
|
|
840
857
|
def __init__(self, config: Config) -> None:
|
841
858
|
self._conf = config
|
842
|
-
self._data = {}
|
859
|
+
self._data: dict[str, dict[str, str | int]] = {}
|
860
|
+
self._map: dict[str, str] = {}
|
843
861
|
return
|
844
862
|
|
845
863
|
def loadCache(self) -> bool:
|
846
864
|
"""Load the cache file for recent projects."""
|
847
865
|
self._data = {}
|
848
|
-
|
866
|
+
self._map = {}
|
849
867
|
cacheFile = self._conf.dataPath(nwFiles.RECENT_FILE)
|
850
868
|
if cacheFile.is_file():
|
851
869
|
try:
|
852
870
|
with open(cacheFile, mode="r", encoding="utf-8") as inFile:
|
853
871
|
data = json.load(inFile)
|
854
872
|
for path, entry in data.items():
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
873
|
+
puuid = str(entry.get("uuid", ""))
|
874
|
+
title = str(entry.get("title", ""))
|
875
|
+
words = checkInt(entry.get("words", 0), 0)
|
876
|
+
saved = checkInt(entry.get("time", 0), 0)
|
877
|
+
if path and title:
|
878
|
+
self._setEntry(puuid, path, title, words, saved)
|
860
879
|
except Exception:
|
861
880
|
logger.error("Could not load recent project cache")
|
862
881
|
logException()
|
863
882
|
return False
|
864
|
-
|
865
883
|
return True
|
866
884
|
|
867
885
|
def saveCache(self) -> bool:
|
@@ -876,7 +894,6 @@ class RecentProjects:
|
|
876
894
|
logger.error("Could not save recent project cache")
|
877
895
|
logException()
|
878
896
|
return False
|
879
|
-
|
880
897
|
return True
|
881
898
|
|
882
899
|
def listEntries(self) -> list[tuple[str, str, int, int]]:
|
@@ -886,14 +903,15 @@ class RecentProjects:
|
|
886
903
|
for k, e in self._data.items()
|
887
904
|
]
|
888
905
|
|
889
|
-
def update(self, path: str | Path,
|
906
|
+
def update(self, path: str | Path, data: NWProjectData, saved: float | int) -> None:
|
890
907
|
"""Add or update recent cache information on a given project."""
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
908
|
+
try:
|
909
|
+
if (remove := self._map.get(data.uuid)) and (remove != str(path)):
|
910
|
+
self.remove(remove)
|
911
|
+
self._setEntry(data.uuid, str(path), data.name, sum(data.currCounts), int(saved))
|
912
|
+
self.saveCache()
|
913
|
+
except Exception:
|
914
|
+
pass
|
897
915
|
return
|
898
916
|
|
899
917
|
def remove(self, path: str | Path) -> None:
|
@@ -903,6 +921,13 @@ class RecentProjects:
|
|
903
921
|
self.saveCache()
|
904
922
|
return
|
905
923
|
|
924
|
+
def _setEntry(self, puuid: str, path: str, title: str, words: int, saved: int) -> None:
|
925
|
+
"""Set an entry in the recent projects record."""
|
926
|
+
self._data[path] = {"uuid": puuid, "title": title, "words": words, "time": saved}
|
927
|
+
if puuid:
|
928
|
+
self._map[puuid] = path
|
929
|
+
return
|
930
|
+
|
906
931
|
|
907
932
|
class RecentPaths:
|
908
933
|
|
novelwriter/constants.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2019-04-28 [0.0.1]
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
@@ -173,6 +173,10 @@ class nwKeyWords:
|
|
173
173
|
TAG_KEY, POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
|
174
174
|
OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, STORY_KEY, MENTION_KEY,
|
175
175
|
]
|
176
|
+
CAN_CREATE = [
|
177
|
+
POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
|
178
|
+
OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY,
|
179
|
+
]
|
176
180
|
|
177
181
|
# Set of Valid Keys
|
178
182
|
VALID_KEYS = set(ALL_KEYS)
|
@@ -207,7 +211,7 @@ class nwLists:
|
|
207
211
|
|
208
212
|
class nwStats:
|
209
213
|
|
210
|
-
|
214
|
+
CHARS = "allChars"
|
211
215
|
CHARS_TEXT = "textChars"
|
212
216
|
CHARS_TITLE = "titleChars"
|
213
217
|
PARAGRAPHS = "paragraphCount"
|
@@ -215,14 +219,14 @@ class nwStats:
|
|
215
219
|
WCHARS_ALL = "allWordChars"
|
216
220
|
WCHARS_TEXT = "textWordChars"
|
217
221
|
WCHARS_TITLE = "titleWordChars"
|
218
|
-
|
222
|
+
WORDS = "allWords"
|
219
223
|
WORDS_TEXT = "textWords"
|
220
224
|
WORDS_TITLE = "titleWords"
|
221
225
|
|
222
226
|
# Note: The order here affects the order of menu entries
|
223
227
|
ALL_FIELDS = [
|
224
|
-
|
225
|
-
|
228
|
+
WORDS, WORDS_TEXT, WORDS_TITLE,
|
229
|
+
CHARS, CHARS_TEXT, CHARS_TITLE,
|
226
230
|
WCHARS_ALL, WCHARS_TEXT, WCHARS_TITLE,
|
227
231
|
PARAGRAPHS, TITLES,
|
228
232
|
]
|
@@ -329,17 +333,17 @@ class nwLabels:
|
|
329
333
|
nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
|
330
334
|
}
|
331
335
|
STATS_NAME = {
|
332
|
-
nwStats.
|
333
|
-
nwStats.CHARS_TEXT: QT_TRANSLATE_NOOP("
|
334
|
-
nwStats.CHARS_TITLE: QT_TRANSLATE_NOOP("
|
335
|
-
nwStats.PARAGRAPHS: QT_TRANSLATE_NOOP("
|
336
|
-
nwStats.TITLES: QT_TRANSLATE_NOOP("
|
337
|
-
nwStats.WCHARS_ALL: QT_TRANSLATE_NOOP("
|
338
|
-
nwStats.WCHARS_TEXT: QT_TRANSLATE_NOOP("
|
339
|
-
nwStats.WCHARS_TITLE: QT_TRANSLATE_NOOP("
|
340
|
-
nwStats.
|
341
|
-
nwStats.WORDS_TEXT: QT_TRANSLATE_NOOP("
|
342
|
-
nwStats.WORDS_TITLE: QT_TRANSLATE_NOOP("
|
336
|
+
nwStats.CHARS: QT_TRANSLATE_NOOP("Stats", "Characters"),
|
337
|
+
nwStats.CHARS_TEXT: QT_TRANSLATE_NOOP("Stats", "Characters in Text"),
|
338
|
+
nwStats.CHARS_TITLE: QT_TRANSLATE_NOOP("Stats", "Characters in Headings"),
|
339
|
+
nwStats.PARAGRAPHS: QT_TRANSLATE_NOOP("Stats", "Paragraphs"),
|
340
|
+
nwStats.TITLES: QT_TRANSLATE_NOOP("Stats", "Headings"),
|
341
|
+
nwStats.WCHARS_ALL: QT_TRANSLATE_NOOP("Stats", "Characters, No Spaces"),
|
342
|
+
nwStats.WCHARS_TEXT: QT_TRANSLATE_NOOP("Stats", "Characters in Text, No Spaces"),
|
343
|
+
nwStats.WCHARS_TITLE: QT_TRANSLATE_NOOP("Stats", "Characters in Headings, No Spaces"),
|
344
|
+
nwStats.WORDS: QT_TRANSLATE_NOOP("Stats", "Words"),
|
345
|
+
nwStats.WORDS_TEXT: QT_TRANSLATE_NOOP("Stats", "Words in Text"),
|
346
|
+
nwStats.WORDS_TITLE: QT_TRANSLATE_NOOP("Stats", "Words in Headings"),
|
343
347
|
}
|
344
348
|
BUILD_FMT = {
|
345
349
|
nwBuildFmt.ODT: QT_TRANSLATE_NOOP("Constant", "Open Document (.odt)"),
|
@@ -366,32 +370,32 @@ class nwLabels:
|
|
366
370
|
nwBuildFmt.J_NWD: ".json",
|
367
371
|
}
|
368
372
|
SHAPES_PLAIN = {
|
369
|
-
nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("
|
370
|
-
nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("
|
371
|
-
nwStatusShape.NABLA: QT_TRANSLATE_NOOP("
|
372
|
-
nwStatusShape.DIAMOND: QT_TRANSLATE_NOOP("
|
373
|
-
nwStatusShape.PENTAGON: QT_TRANSLATE_NOOP("
|
374
|
-
nwStatusShape.HEXAGON: QT_TRANSLATE_NOOP("
|
375
|
-
nwStatusShape.STAR: QT_TRANSLATE_NOOP("
|
376
|
-
nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("
|
373
|
+
nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Shape", "Square"),
|
374
|
+
nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Shape", "Triangle"),
|
375
|
+
nwStatusShape.NABLA: QT_TRANSLATE_NOOP("Shape", "Nabla"),
|
376
|
+
nwStatusShape.DIAMOND: QT_TRANSLATE_NOOP("Shape", "Diamond"),
|
377
|
+
nwStatusShape.PENTAGON: QT_TRANSLATE_NOOP("Shape", "Pentagon"),
|
378
|
+
nwStatusShape.HEXAGON: QT_TRANSLATE_NOOP("Shape", "Hexagon"),
|
379
|
+
nwStatusShape.STAR: QT_TRANSLATE_NOOP("Shape", "Star"),
|
380
|
+
nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Shape", "Pacman"),
|
377
381
|
}
|
378
382
|
SHAPES_CIRCLE = {
|
379
|
-
nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("
|
380
|
-
nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("
|
381
|
-
nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("
|
382
|
-
nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("
|
383
|
+
nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("Shape", "1/4 Circle"),
|
384
|
+
nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("Shape", "Half Circle"),
|
385
|
+
nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("Shape", "3/4 Circle"),
|
386
|
+
nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Shape", "Full Circle"),
|
383
387
|
}
|
384
388
|
SHAPES_BARS = {
|
385
|
-
nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("
|
386
|
-
nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("
|
387
|
-
nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("
|
388
|
-
nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("
|
389
|
+
nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("Shape", "1 Bar"),
|
390
|
+
nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("Shape", "2 Bars"),
|
391
|
+
nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("Shape", "3 Bars"),
|
392
|
+
nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("Shape", "4 Bars"),
|
389
393
|
}
|
390
394
|
SHAPES_BLOCKS = {
|
391
|
-
nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("
|
392
|
-
nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("
|
393
|
-
nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("
|
394
|
-
nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("
|
395
|
+
nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("Shape", "1 Block"),
|
396
|
+
nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("Shape", "2 Blocks"),
|
397
|
+
nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("Shape", "3 Blocks"),
|
398
|
+
nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("Shape", "4 Blocks"),
|
395
399
|
}
|
396
400
|
FILE_FILTERS = {
|
397
401
|
"*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"),
|
@@ -7,7 +7,7 @@ Created: 2023-02-14 [2.1b1] BuildSettings
|
|
7
7
|
Created: 2023-05-22 [2.1b1] BuildCollection
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
@@ -159,6 +159,13 @@ SETTINGS_LABELS = {
|
|
159
159
|
"format.indentFirstPar": QT_TRANSLATE_NOOP("Builds", "Indent First Paragraph"),
|
160
160
|
|
161
161
|
"format.grpMargins": QT_TRANSLATE_NOOP("Builds", "Text Margins"),
|
162
|
+
"format.titleMargin": QT_TRANSLATE_NOOP("Builds", "Title and Partition"),
|
163
|
+
"format.h1Margin": QT_TRANSLATE_NOOP("Builds", "Heading 1 and Chapter"),
|
164
|
+
"format.h2Margin": QT_TRANSLATE_NOOP("Builds", "Heading 2 and Scene"),
|
165
|
+
"format.h3Margin": QT_TRANSLATE_NOOP("Builds", "Heading 3 and Section"),
|
166
|
+
"format.h4Margin": QT_TRANSLATE_NOOP("Builds", "Heading 4"),
|
167
|
+
"format.textMargin": QT_TRANSLATE_NOOP("Builds", "Text Paragraph"),
|
168
|
+
"format.sepMargin": QT_TRANSLATE_NOOP("Builds", "Scene Separator"),
|
162
169
|
|
163
170
|
"format.grpPage": QT_TRANSLATE_NOOP("Builds", "Page Layout"),
|
164
171
|
"format.pageUnit": QT_TRANSLATE_NOOP("Builds", "Unit"),
|
novelwriter/core/coretools.py
CHANGED
@@ -9,7 +9,7 @@ Created: 2022-11-03 [2.0rc2] ProjectBuilder
|
|
9
9
|
Created: 2023-07-20 [2.1b1] DocDuplicator
|
10
10
|
|
11
11
|
This file is a part of novelWriter
|
12
|
-
Copyright
|
12
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
13
13
|
|
14
14
|
This program is free software: you can redistribute it and/or modify
|
15
15
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/docbuild.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2022-12-01 [2.1b1] NWBuildDocument
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/document.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2018-09-29 [0.0.1]
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018
|
9
|
+
Copyright (C) 2018 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/index.py
CHANGED
@@ -10,7 +10,7 @@ Created: 2022-05-29 [2.0rc1] TagsIndex
|
|
10
10
|
Created: 2022-05-29 [2.0rc1] ItemIndex
|
11
11
|
|
12
12
|
This file is a part of novelWriter
|
13
|
-
Copyright
|
13
|
+
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
14
14
|
|
15
15
|
This program is free software: you can redistribute it and/or modify
|
16
16
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/item.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2018-10-27 [0.0.1] NWItem
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018
|
9
|
+
Copyright (C) 2018 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/itemmodel.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2024-11-16 [2.6b2] ProjectNode
|
|
7
7
|
Created: 2024-11-16 [2.6b2] ProjectModel
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/options.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2019-10-21 [0.3.1] OptionState
|
|
7
7
|
Rewritten: 2020-02-19 [0.4.5] OptionState
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/project.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2018-09-29 [0.0.1] NWProject
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018
|
9
|
+
Copyright (C) 2018 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
@@ -353,9 +353,7 @@ class NWProject:
|
|
353
353
|
|
354
354
|
# Update recent projects
|
355
355
|
if storePath := self._storage.storagePath:
|
356
|
-
CONFIG.recentProjects.update(
|
357
|
-
storePath, self._data.name, sum(self._data.initCounts), time()
|
358
|
-
)
|
356
|
+
CONFIG.recentProjects.update(storePath, self._data, time())
|
359
357
|
|
360
358
|
# Check the project tree consistency
|
361
359
|
# This also handles any orphaned files found
|
@@ -421,9 +419,7 @@ class NWProject:
|
|
421
419
|
|
422
420
|
# Update recent projects
|
423
421
|
if storagePath := self._storage.storagePath:
|
424
|
-
CONFIG.recentProjects.update(
|
425
|
-
storagePath, self._data.name, sum(self._data.currCounts), saveTime
|
426
|
-
)
|
422
|
+
CONFIG.recentProjects.update(storagePath, self._data, saveTime)
|
427
423
|
|
428
424
|
SHARED.newStatusMessage(self.tr("Saved Project: {0}").format(self._data.name))
|
429
425
|
self.setProjectChanged(False)
|
novelwriter/core/projectdata.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2022-10-30 [2.0rc2] NWProjectData
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
@@ -29,7 +29,8 @@ import uuid
|
|
29
29
|
from typing import TYPE_CHECKING, Any
|
30
30
|
|
31
31
|
from novelwriter.common import (
|
32
|
-
checkBool, checkInt, checkStringNone, checkUuid, isHandle,
|
32
|
+
checkBool, checkInt, checkStringNone, checkUuid, isHandle,
|
33
|
+
makeFileNameSafe, simplified
|
33
34
|
)
|
34
35
|
from novelwriter.core.status import NWStatus
|
35
36
|
|
@@ -101,6 +102,11 @@ class NWProjectData:
|
|
101
102
|
"""Return the project name."""
|
102
103
|
return self._name
|
103
104
|
|
105
|
+
@property
|
106
|
+
def fileSafeName(self) -> str:
|
107
|
+
"""Return the project name in a file name safe format."""
|
108
|
+
return makeFileNameSafe(self._name)
|
109
|
+
|
104
110
|
@property
|
105
111
|
def author(self) -> str:
|
106
112
|
"""Return the project author."""
|
novelwriter/core/projectxml.py
CHANGED
@@ -8,7 +8,7 @@ Created: 2022-09-28 [2.0rc2] ProjectXMLReader
|
|
8
8
|
Created: 2022-10-31 [2.0rc2] ProjectXMLWriter
|
9
9
|
|
10
10
|
This file is a part of novelWriter
|
11
|
-
Copyright
|
11
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
12
12
|
|
13
13
|
This program is free software: you can redistribute it and/or modify
|
14
14
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/sessions.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2023-06-11 [2.1b1] NWSessionLog
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/spellcheck.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2019-06-11 [0.1.5] NWSpellEnchant
|
|
7
7
|
Created: 2023-06-13 [2.1b1] UserDictionary
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/status.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2019-05-19 [0.1.3] NWStatus
|
|
7
7
|
Rewritten: 2022-04-05 [2.0b1] NWStatus
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
@@ -37,7 +37,7 @@ from PyQt5.QtGui import QColor, QIcon, QPainter, QPainterPath, QPixmap, QPolygon
|
|
37
37
|
from novelwriter import SHARED
|
38
38
|
from novelwriter.common import simplified
|
39
39
|
from novelwriter.enum import nwStatusShape
|
40
|
-
from novelwriter.types import
|
40
|
+
from novelwriter.types import QtPaintAntiAlias, QtTransparent
|
41
41
|
|
42
42
|
if TYPE_CHECKING: # pragma: no cover
|
43
43
|
from typing import TypeGuard # Requires Python 3.10
|
@@ -174,6 +174,20 @@ class NWStatus:
|
|
174
174
|
"""Yield entries from the status icons."""
|
175
175
|
yield from self._store.items()
|
176
176
|
|
177
|
+
def fromRaw(self, data: list[str]) -> StatusEntry | None:
|
178
|
+
"""Create a StatusEntry from a list of three strings consisting
|
179
|
+
of shape, colour, and name. This entry is not automatically
|
180
|
+
added to the list of entries.
|
181
|
+
"""
|
182
|
+
try:
|
183
|
+
shape = nwStatusShape[str(data[0])]
|
184
|
+
color = QColor(str(data[1]))
|
185
|
+
icon = NWStatus.createIcon(self._height, color, shape)
|
186
|
+
return StatusEntry(simplified(data[2]), color, shape, icon)
|
187
|
+
except Exception:
|
188
|
+
logger.error("Could not parse entry %s", str(data))
|
189
|
+
return None
|
190
|
+
|
177
191
|
@staticmethod
|
178
192
|
def createIcon(height: int, color: QColor, shape: nwStatusShape) -> QIcon:
|
179
193
|
"""Generate an icon for a status label."""
|
@@ -181,7 +195,7 @@ class NWStatus:
|
|
181
195
|
pixmap.fill(QtTransparent)
|
182
196
|
|
183
197
|
painter = QPainter(pixmap)
|
184
|
-
painter.setRenderHint(
|
198
|
+
painter.setRenderHint(QtPaintAntiAlias)
|
185
199
|
painter.fillPath(_SHAPES.getShape(shape), color)
|
186
200
|
painter.end()
|
187
201
|
|
novelwriter/core/storage.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2022-11-01 [2.0rc2] NWStorage
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/core/tree.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2020-05-07 [0.4.5] NWTree
|
|
7
7
|
Rewritten: 2024-11-16 [2.6b2] NWTree
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/dialogs/about.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2020-05-21 [0.5.2] GuiAbout
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
novelwriter/dialogs/docmerge.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2020-01-23 [0.4.3] GuiDocMerge
|
|
7
7
|
Rewritten: 2022-10-06 [2.0rc1] GuiDocMerge
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/dialogs/docsplit.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2020-02-01 [0.4.3] GuiDocSplit
|
|
7
7
|
Rewritten: 2022-10-12 [2.0rc1] GuiDocSplit
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright
|
10
|
+
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/dialogs/editlabel.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2022-06-11 [2.0rc1] GuiEditLabel
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright
|
9
|
+
Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|