novelWriter 2.2rc1__py3-none-any.whl → 2.3b1__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.2rc1.dist-info → novelWriter-2.3b1.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/RECORD +141 -129
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +11 -6
- 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_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +1 -0
- novelwriter/assets/i18n/project_en_US.json +1 -0
- novelwriter/assets/i18n/project_es_419.json +11 -0
- novelwriter/assets/i18n/project_fr_FR.json +11 -0
- novelwriter/assets/i18n/project_it_IT.json +11 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -1
- novelwriter/assets/i18n/project_nb_NO.json +1 -0
- novelwriter/assets/i18n/project_zh_CN.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +9 -2
- novelwriter/assets/icons/typicons_dark/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_dark/typ_document-add-col.svg +8 -0
- novelwriter/assets/icons/typicons_dark/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +9 -2
- novelwriter/assets/icons/typicons_light/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_light/typ_document-add-col.svg +8 -0
- novelwriter/assets/icons/typicons_light/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +4 -0
- novelwriter/assets/images/novelwriter-text-dark.svg +4 -0
- novelwriter/assets/images/novelwriter-text-light.svg +4 -0
- novelwriter/assets/images/welcome-dark.jpg +0 -0
- novelwriter/assets/images/welcome-light.jpg +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +4 -2
- novelwriter/assets/themes/default_dark.conf +2 -2
- novelwriter/assets/themes/default_light.conf +2 -2
- novelwriter/common.py +64 -66
- novelwriter/config.py +39 -44
- novelwriter/constants.py +39 -17
- novelwriter/core/buildsettings.py +8 -8
- novelwriter/core/coretools.py +194 -155
- novelwriter/core/docbuild.py +7 -4
- novelwriter/core/document.py +7 -7
- novelwriter/core/index.py +90 -57
- novelwriter/core/item.py +23 -5
- novelwriter/core/options.py +11 -10
- novelwriter/core/project.py +72 -47
- novelwriter/core/projectdata.py +3 -16
- novelwriter/core/projectxml.py +14 -42
- novelwriter/core/sessions.py +4 -3
- novelwriter/core/spellcheck.py +6 -4
- novelwriter/core/status.py +5 -4
- novelwriter/core/storage.py +179 -141
- novelwriter/core/tohtml.py +6 -4
- novelwriter/core/tokenizer.py +74 -46
- novelwriter/core/tomd.py +2 -2
- novelwriter/core/toodt.py +41 -31
- novelwriter/core/tree.py +5 -4
- novelwriter/dialogs/about.py +88 -179
- novelwriter/dialogs/docmerge.py +30 -20
- novelwriter/dialogs/docsplit.py +33 -22
- novelwriter/dialogs/editlabel.py +20 -8
- novelwriter/dialogs/preferences.py +562 -725
- novelwriter/dialogs/{projsettings.py → projectsettings.py} +301 -270
- novelwriter/dialogs/quotes.py +47 -36
- novelwriter/dialogs/wordlist.py +128 -59
- novelwriter/enum.py +25 -22
- novelwriter/error.py +2 -2
- novelwriter/extensions/circularprogress.py +12 -12
- novelwriter/extensions/configlayout.py +185 -146
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/modified.py +81 -0
- novelwriter/extensions/novelselector.py +27 -13
- novelwriter/extensions/pagedsidebar.py +15 -20
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +9 -9
- novelwriter/extensions/switch.py +32 -64
- novelwriter/extensions/switchbox.py +2 -7
- novelwriter/extensions/versioninfo.py +153 -0
- novelwriter/gui/doceditor.py +250 -214
- novelwriter/gui/dochighlight.py +66 -94
- novelwriter/gui/docviewer.py +71 -98
- novelwriter/gui/docviewerpanel.py +140 -47
- novelwriter/gui/editordocument.py +3 -3
- novelwriter/gui/itemdetails.py +9 -9
- novelwriter/gui/mainmenu.py +47 -46
- novelwriter/gui/noveltree.py +53 -61
- novelwriter/gui/outline.py +100 -76
- novelwriter/gui/projtree.py +193 -67
- novelwriter/gui/sidebar.py +9 -8
- novelwriter/gui/statusbar.py +49 -7
- novelwriter/gui/theme.py +65 -74
- novelwriter/guimain.py +173 -330
- novelwriter/shared.py +68 -30
- novelwriter/tools/dictionaries.py +7 -8
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +3 -4
- novelwriter/tools/manuscript.py +25 -32
- novelwriter/tools/manussettings.py +194 -225
- novelwriter/tools/noveldetails.py +525 -0
- novelwriter/tools/welcome.py +802 -0
- novelwriter/tools/writingstats.py +26 -13
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/images/wizard-back.jpg +0 -0
- novelwriter/assets/text/gplv3_en.htm +0 -641
- novelwriter/assets/text/release_notes.htm +0 -17
- novelwriter/dialogs/projdetails.py +0 -525
- novelwriter/dialogs/projload.py +0 -298
- novelwriter/dialogs/updates.py +0 -182
- novelwriter/extensions/pageddialog.py +0 -130
- novelwriter/tools/projwizard.py +0 -478
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/top_level.txt +0 -0
novelwriter/shared.py
CHANGED
@@ -3,10 +3,11 @@ novelWriter – Shared Data Class
|
|
3
3
|
===============================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2023-08-10 [2.1rc1]
|
6
|
+
Created: 2023-08-10 [2.1rc1] SharedData
|
7
|
+
Created: 2023-08-14 [2.1rc1] _GuiAlert
|
7
8
|
|
8
9
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
10
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
11
|
|
11
12
|
This program is free software: you can redistribute it and/or modify
|
12
13
|
it under the terms of the GNU General Public License as published by
|
@@ -26,12 +27,14 @@ from __future__ import annotations
|
|
26
27
|
import logging
|
27
28
|
|
28
29
|
from time import time
|
29
|
-
from typing import TYPE_CHECKING
|
30
|
+
from typing import TYPE_CHECKING, TypeVar
|
30
31
|
from pathlib import Path
|
31
32
|
|
32
33
|
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
|
33
|
-
from PyQt5.QtWidgets import QMessageBox, QWidget
|
34
|
+
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
|
35
|
+
from novelwriter.common import formatFileFilter
|
34
36
|
|
37
|
+
from novelwriter.constants import nwFiles
|
35
38
|
from novelwriter.core.spellcheck import NWSpellEnchant
|
36
39
|
|
37
40
|
if TYPE_CHECKING: # pragma: no cover
|
@@ -41,11 +44,13 @@ if TYPE_CHECKING: # pragma: no cover
|
|
41
44
|
|
42
45
|
logger = logging.getLogger(__name__)
|
43
46
|
|
47
|
+
NWWidget = TypeVar("NWWidget", bound=QWidget)
|
48
|
+
|
44
49
|
|
45
50
|
class SharedData(QObject):
|
46
51
|
|
47
52
|
__slots__ = (
|
48
|
-
"_gui", "_theme", "_project", "_spelling", "_lockedBy", "
|
53
|
+
"_gui", "_theme", "_project", "_spelling", "_lockedBy", "_lastAlert",
|
49
54
|
"_idleTime", "_idleRefTime",
|
50
55
|
)
|
51
56
|
|
@@ -68,7 +73,7 @@ class SharedData(QObject):
|
|
68
73
|
|
69
74
|
# Settings
|
70
75
|
self._lockedBy = None
|
71
|
-
self.
|
76
|
+
self._lastAlert = ""
|
72
77
|
self._idleTime = 0.0
|
73
78
|
self._idleRefTime = time()
|
74
79
|
|
@@ -122,9 +127,9 @@ class SharedData(QObject):
|
|
122
127
|
return self._idleTime
|
123
128
|
|
124
129
|
@property
|
125
|
-
def
|
126
|
-
"""Return
|
127
|
-
return self.
|
130
|
+
def lastAlert(self) -> str:
|
131
|
+
"""Return the last alert message."""
|
132
|
+
return self._lastAlert
|
128
133
|
|
129
134
|
##
|
130
135
|
# Methods
|
@@ -214,6 +219,25 @@ class SharedData(QObject):
|
|
214
219
|
QThreadPool.globalInstance().start(runnable, priority=priority)
|
215
220
|
return
|
216
221
|
|
222
|
+
def getProjectPath(self, parent: QWidget, path: str | Path | None = None,
|
223
|
+
allowZip: bool = False) -> Path | None:
|
224
|
+
"""Open the file dialog and select a novelWriter project file."""
|
225
|
+
label = (self.tr("novelWriter Project File or Zip File")
|
226
|
+
if allowZip else self.tr("novelWriter Project File"))
|
227
|
+
ext = f"{nwFiles.PROJ_FILE} *.zip" if allowZip else nwFiles.PROJ_FILE
|
228
|
+
ffilter = formatFileFilter([(label, ext), "*"])
|
229
|
+
selected, _ = QFileDialog.getOpenFileName(
|
230
|
+
parent, self.tr("Open Project"), str(path or ""), filter=ffilter
|
231
|
+
)
|
232
|
+
return Path(selected) if selected else None
|
233
|
+
|
234
|
+
def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
|
235
|
+
"""Find a top level widget."""
|
236
|
+
for widget in self.mainGui.children():
|
237
|
+
if isinstance(widget, kind):
|
238
|
+
return widget
|
239
|
+
return None
|
240
|
+
|
217
241
|
##
|
218
242
|
# Signal Proxy
|
219
243
|
##
|
@@ -238,44 +262,53 @@ class SharedData(QObject):
|
|
238
262
|
|
239
263
|
def info(self, text: str, info: str = "", details: str = "", log: bool = True) -> None:
|
240
264
|
"""Open an information alert box."""
|
241
|
-
|
242
|
-
|
243
|
-
|
265
|
+
alert = _GuiAlert(self.mainGui, self.theme)
|
266
|
+
alert.setMessage(text, info, details)
|
267
|
+
alert.setAlertType(_GuiAlert.INFO, False)
|
268
|
+
self._lastAlert = alert.logMessage
|
244
269
|
if log:
|
245
|
-
logger.info(self.
|
246
|
-
|
270
|
+
logger.info(self._lastAlert, stacklevel=2)
|
271
|
+
alert.exec_()
|
272
|
+
alert.deleteLater()
|
247
273
|
return
|
248
274
|
|
249
275
|
def warn(self, text: str, info: str = "", details: str = "", log: bool = True) -> None:
|
250
276
|
"""Open a warning alert box."""
|
251
|
-
|
252
|
-
|
253
|
-
|
277
|
+
alert = _GuiAlert(self.mainGui, self.theme)
|
278
|
+
alert.setMessage(text, info, details)
|
279
|
+
alert.setAlertType(_GuiAlert.WARN, False)
|
280
|
+
self._lastAlert = alert.logMessage
|
254
281
|
if log:
|
255
|
-
logger.warning(self.
|
256
|
-
|
282
|
+
logger.warning(self._lastAlert, stacklevel=2)
|
283
|
+
alert.exec_()
|
284
|
+
alert.deleteLater()
|
257
285
|
return
|
258
286
|
|
259
287
|
def error(self, text: str, info: str = "", details: str = "", log: bool = True,
|
260
288
|
exc: Exception | None = None) -> None:
|
261
289
|
"""Open an error alert box."""
|
262
|
-
|
263
|
-
|
264
|
-
|
290
|
+
alert = _GuiAlert(self.mainGui, self.theme)
|
291
|
+
alert.setMessage(text, info, details)
|
292
|
+
alert.setAlertType(_GuiAlert.ERROR, False)
|
265
293
|
if exc:
|
266
|
-
|
294
|
+
alert.setException(exc)
|
295
|
+
self._lastAlert = alert.logMessage
|
267
296
|
if log:
|
268
|
-
logger.error(self.
|
269
|
-
|
297
|
+
logger.error(self._lastAlert, stacklevel=2)
|
298
|
+
alert.exec_()
|
299
|
+
alert.deleteLater()
|
270
300
|
return
|
271
301
|
|
272
302
|
def question(self, text: str, info: str = "", details: str = "", warn: bool = False) -> bool:
|
273
303
|
"""Open a question box."""
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
self.
|
278
|
-
|
304
|
+
alert = _GuiAlert(self.mainGui, self.theme)
|
305
|
+
alert.setMessage(text, info, details)
|
306
|
+
alert.setAlertType(_GuiAlert.WARN if warn else _GuiAlert.ASK, True)
|
307
|
+
self._lastAlert = alert.logMessage
|
308
|
+
alert.exec_()
|
309
|
+
isYes = alert.result() == QMessageBox.StandardButton.Yes
|
310
|
+
alert.deleteLater()
|
311
|
+
return isYes
|
279
312
|
|
280
313
|
##
|
281
314
|
# Internal Functions
|
@@ -312,6 +345,11 @@ class _GuiAlert(QMessageBox):
|
|
312
345
|
super().__init__(parent=parent)
|
313
346
|
self._theme = theme
|
314
347
|
self._message = ""
|
348
|
+
logger.debug("Ready: _GuiAlert")
|
349
|
+
return
|
350
|
+
|
351
|
+
def __del__(self) -> None: # pragma: no cover
|
352
|
+
logger.debug("Delete: _GuiAlert")
|
315
353
|
return
|
316
354
|
|
317
355
|
@property
|
@@ -3,10 +3,10 @@ novelWriter – GUI Dictionary Downloader
|
|
3
3
|
=======================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2023-11-19 [2.2rc1]
|
6
|
+
Created: 2023-11-19 [2.2rc1] GuiDictionaries
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
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
|
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
|
|
37
37
|
|
38
38
|
from novelwriter import CONFIG, SHARED
|
39
39
|
from novelwriter.error import formatException
|
40
|
-
from novelwriter.common import openExternalPath, formatInt, getFileSize
|
40
|
+
from novelwriter.common import formatFileFilter, openExternalPath, formatInt, getFileSize
|
41
41
|
|
42
42
|
logger = logging.getLogger(__name__)
|
43
43
|
|
@@ -180,12 +180,11 @@ class GuiDictionaries(QDialog):
|
|
180
180
|
@pyqtSlot()
|
181
181
|
def _doBrowseHunspell(self):
|
182
182
|
"""Browse for a Free/Libre Office dictionary."""
|
183
|
-
|
184
|
-
self.tr("Free or Libre Office extension
|
185
|
-
|
186
|
-
]
|
183
|
+
ffilter = formatFileFilter([
|
184
|
+
(self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
|
185
|
+
])
|
187
186
|
soxFile, _ = QFileDialog.getOpenFileName(
|
188
|
-
self, self.tr("Browse Files"), "", filter=
|
187
|
+
self, self.tr("Browse Files"), "", filter=ffilter
|
189
188
|
)
|
190
189
|
if soxFile:
|
191
190
|
path = Path(soxFile).absolute()
|
novelwriter/tools/lipsum.py
CHANGED
@@ -3,10 +3,10 @@ novelWriter – Lorem Ipsum Tool
|
|
3
3
|
==============================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2022-04-02 [2.0rc1]
|
6
|
+
Created: 2022-04-02 [2.0rc1] GuiLipsum
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
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
|
@@ -26,10 +26,10 @@ from __future__ import annotations
|
|
26
26
|
import random
|
27
27
|
import logging
|
28
28
|
|
29
|
-
from PyQt5.QtCore import Qt
|
29
|
+
from PyQt5.QtCore import Qt, pyqtSlot
|
30
30
|
from PyQt5.QtWidgets import (
|
31
|
-
QDialog, QGridLayout, QHBoxLayout,
|
32
|
-
|
31
|
+
QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel, QSpinBox,
|
32
|
+
QVBoxLayout, QWidget
|
33
33
|
)
|
34
34
|
|
35
35
|
from novelwriter import CONFIG, SHARED
|
@@ -41,15 +41,15 @@ logger = logging.getLogger(__name__)
|
|
41
41
|
|
42
42
|
class GuiLipsum(QDialog):
|
43
43
|
|
44
|
-
def __init__(self,
|
45
|
-
super().__init__(parent=
|
44
|
+
def __init__(self, parent: QWidget) -> None:
|
45
|
+
super().__init__(parent=parent)
|
46
46
|
|
47
47
|
logger.debug("Create: GuiLipsum")
|
48
48
|
self.setObjectName("GuiLipsum")
|
49
49
|
if CONFIG.osDarwin:
|
50
50
|
self.setWindowFlag(Qt.WindowType.Tool)
|
51
51
|
|
52
|
-
self.
|
52
|
+
self._lipsumText = ""
|
53
53
|
|
54
54
|
self.setWindowTitle(self.tr("Insert Placeholder Text"))
|
55
55
|
|
@@ -92,14 +92,16 @@ class GuiLipsum(QDialog):
|
|
92
92
|
|
93
93
|
# Buttons
|
94
94
|
self.buttonBox = QDialogButtonBox()
|
95
|
-
self.buttonBox.rejected.connect(self.
|
95
|
+
self.buttonBox.rejected.connect(self.close)
|
96
96
|
|
97
97
|
self.btnClose = self.buttonBox.addButton(QDialogButtonBox.Close)
|
98
98
|
self.btnClose.setAutoDefault(False)
|
99
99
|
|
100
|
-
self.
|
101
|
-
self.
|
102
|
-
self.
|
100
|
+
self.btnInsert = self.buttonBox.addButton(self.tr("Insert"), QDialogButtonBox.ActionRole)
|
101
|
+
self.btnInsert.clicked.connect(self._doInsert)
|
102
|
+
self.btnInsert.setAutoDefault(False)
|
103
|
+
|
104
|
+
self.rejected.connect(self.close)
|
103
105
|
|
104
106
|
# Assemble
|
105
107
|
self.outerBox = QVBoxLayout()
|
@@ -112,33 +114,37 @@ class GuiLipsum(QDialog):
|
|
112
114
|
|
113
115
|
return
|
114
116
|
|
115
|
-
def __del__(self): # pragma: no cover
|
117
|
+
def __del__(self) -> None: # pragma: no cover
|
116
118
|
logger.debug("Delete: GuiLipsum")
|
117
119
|
return
|
118
120
|
|
121
|
+
@property
|
122
|
+
def lipsumText(self) -> str:
|
123
|
+
"""Return the generated text."""
|
124
|
+
return self._lipsumText
|
125
|
+
|
126
|
+
@classmethod
|
127
|
+
def getLipsum(cls, parent: QWidget) -> str:
|
128
|
+
"""Pop the dialog and return the lipsum text."""
|
129
|
+
cls = GuiLipsum(parent)
|
130
|
+
cls.exec_()
|
131
|
+
text = cls.lipsumText
|
132
|
+
cls.deleteLater()
|
133
|
+
return text
|
134
|
+
|
119
135
|
##
|
120
|
-
# Slots
|
136
|
+
# Private Slots
|
121
137
|
##
|
122
138
|
|
123
|
-
|
124
|
-
|
125
|
-
"""
|
139
|
+
@pyqtSlot()
|
140
|
+
def _doInsert(self) -> None:
|
141
|
+
"""Generate the text."""
|
126
142
|
lipsumFile = CONFIG.assetPath("text") / "lipsum.txt"
|
127
143
|
lipsumText = readTextFile(lipsumFile).splitlines()
|
128
|
-
|
129
144
|
if self.randSwitch.isChecked():
|
130
145
|
random.shuffle(lipsumText)
|
131
|
-
|
132
146
|
pCount = self.paraCount.value()
|
133
|
-
|
134
|
-
|
135
|
-
self.mainGui.docEditor.insertText(inText)
|
136
|
-
|
137
|
-
return
|
138
|
-
|
139
|
-
def _doClose(self):
|
140
|
-
"""Close the dialog window without doing anything.
|
141
|
-
"""
|
147
|
+
self._lipsumText = "\n\n".join(lipsumText[0:pCount]) + "\n\n"
|
142
148
|
self.close()
|
143
149
|
return
|
144
150
|
|
novelwriter/tools/manusbuild.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2023-05-24 [2.1b1] GuiManuscriptBuild
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
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
|
@@ -331,7 +331,7 @@ class GuiManuscriptBuild(QDialog):
|
|
331
331
|
self._build.setLastBuildName(bName)
|
332
332
|
self._build.setLastFormat(bFormat)
|
333
333
|
|
334
|
-
QTimer.singleShot(
|
334
|
+
QTimer.singleShot(3000, self._resetProgress)
|
335
335
|
|
336
336
|
return True
|
337
337
|
|
@@ -344,8 +344,6 @@ class GuiManuscriptBuild(QDialog):
|
|
344
344
|
|
345
345
|
def _saveSettings(self):
|
346
346
|
"""Save the user GUI settings."""
|
347
|
-
logger.debug("Saving GuiManuscriptBuild settings")
|
348
|
-
|
349
347
|
winWidth = CONFIG.rpxInt(self.width())
|
350
348
|
winHeight = CONFIG.rpxInt(self.height())
|
351
349
|
|
@@ -353,6 +351,7 @@ class GuiManuscriptBuild(QDialog):
|
|
353
351
|
fmtWidth = CONFIG.rpxInt(mainSplit[0])
|
354
352
|
sumWidth = CONFIG.rpxInt(mainSplit[1])
|
355
353
|
|
354
|
+
logger.debug("Saving State: GuiManuscriptBuild")
|
356
355
|
pOptions = SHARED.project.options
|
357
356
|
pOptions.setValue("GuiManuscriptBuild", "winWidth", winWidth)
|
358
357
|
pOptions.setValue("GuiManuscriptBuild", "winHeight", winHeight)
|
novelwriter/tools/manuscript.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2023-05-13 [2.1b1] GuiManuscript
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
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
|
@@ -66,7 +66,7 @@ class GuiManuscript(QDialog):
|
|
66
66
|
|
67
67
|
D_KEY = Qt.ItemDataRole.UserRole
|
68
68
|
|
69
|
-
def __init__(self, mainGui: GuiMain):
|
69
|
+
def __init__(self, mainGui: GuiMain) -> None:
|
70
70
|
super().__init__(parent=mainGui)
|
71
71
|
|
72
72
|
logger.debug("Create: GuiManuscript")
|
@@ -173,7 +173,7 @@ class GuiManuscript(QDialog):
|
|
173
173
|
self.btnBuild.clicked.connect(self._buildManuscript)
|
174
174
|
|
175
175
|
self.btnClose = QPushButton(self.tr("Close"))
|
176
|
-
self.btnClose.clicked.connect(self.
|
176
|
+
self.btnClose.clicked.connect(self.close)
|
177
177
|
|
178
178
|
self.processBox = QGridLayout()
|
179
179
|
self.processBox.addWidget(self.btnPreview, 0, 0)
|
@@ -217,11 +217,11 @@ class GuiManuscript(QDialog):
|
|
217
217
|
|
218
218
|
return
|
219
219
|
|
220
|
-
def __del__(self): # pragma: no cover
|
220
|
+
def __del__(self) -> None: # pragma: no cover
|
221
221
|
logger.debug("Delete: GuiManuscript")
|
222
222
|
return
|
223
223
|
|
224
|
-
def loadContent(self):
|
224
|
+
def loadContent(self) -> None:
|
225
225
|
"""Load dialog content from project data."""
|
226
226
|
if len(self._builds) == 0:
|
227
227
|
build = BuildSettings()
|
@@ -255,7 +255,7 @@ class GuiManuscript(QDialog):
|
|
255
255
|
# Events
|
256
256
|
##
|
257
257
|
|
258
|
-
def closeEvent(self, event: QCloseEvent):
|
258
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
259
259
|
"""Capture the user closing the window so we can save GUI
|
260
260
|
settings. We also check that we don't have a build settings
|
261
261
|
dialog open.
|
@@ -274,7 +274,7 @@ class GuiManuscript(QDialog):
|
|
274
274
|
##
|
275
275
|
|
276
276
|
@pyqtSlot()
|
277
|
-
def _createNewBuild(self):
|
277
|
+
def _createNewBuild(self) -> None:
|
278
278
|
"""Open the build settings dialog for a new build."""
|
279
279
|
build = BuildSettings()
|
280
280
|
build.setName(self.tr("My Manuscript"))
|
@@ -282,7 +282,7 @@ class GuiManuscript(QDialog):
|
|
282
282
|
return
|
283
283
|
|
284
284
|
@pyqtSlot()
|
285
|
-
def _editSelectedBuild(self):
|
285
|
+
def _editSelectedBuild(self) -> None:
|
286
286
|
"""Edit the currently selected build settings entry."""
|
287
287
|
build = self._getSelectedBuild()
|
288
288
|
if build is not None:
|
@@ -299,7 +299,7 @@ class GuiManuscript(QDialog):
|
|
299
299
|
return
|
300
300
|
|
301
301
|
@pyqtSlot()
|
302
|
-
def _deleteSelectedBuild(self):
|
302
|
+
def _deleteSelectedBuild(self) -> None:
|
303
303
|
"""Delete the currently selected build settings entry."""
|
304
304
|
build = self._getSelectedBuild()
|
305
305
|
if build is not None:
|
@@ -309,7 +309,7 @@ class GuiManuscript(QDialog):
|
|
309
309
|
return
|
310
310
|
|
311
311
|
@pyqtSlot(BuildSettings)
|
312
|
-
def _processNewSettings(self, build: BuildSettings):
|
312
|
+
def _processNewSettings(self, build: BuildSettings) -> None:
|
313
313
|
"""Process new build settings from the settings dialog."""
|
314
314
|
self._builds.setBuild(build)
|
315
315
|
self._updateBuildItem(build)
|
@@ -319,7 +319,7 @@ class GuiManuscript(QDialog):
|
|
319
319
|
return
|
320
320
|
|
321
321
|
@pyqtSlot()
|
322
|
-
def _generatePreview(self):
|
322
|
+
def _generatePreview(self) -> None:
|
323
323
|
"""Run the document builder on the current build settings for
|
324
324
|
the preview widget.
|
325
325
|
"""
|
@@ -359,7 +359,7 @@ class GuiManuscript(QDialog):
|
|
359
359
|
return
|
360
360
|
|
361
361
|
@pyqtSlot()
|
362
|
-
def _buildManuscript(self):
|
362
|
+
def _buildManuscript(self) -> None:
|
363
363
|
"""Open the build dialog and build the manuscript."""
|
364
364
|
build = self._getSelectedBuild()
|
365
365
|
if isinstance(build, BuildSettings):
|
@@ -373,24 +373,18 @@ class GuiManuscript(QDialog):
|
|
373
373
|
return
|
374
374
|
|
375
375
|
@pyqtSlot()
|
376
|
-
def _printDocument(self):
|
376
|
+
def _printDocument(self) -> None:
|
377
377
|
"""Open the print preview dialog."""
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
return
|
382
|
-
|
383
|
-
@pyqtSlot()
|
384
|
-
def _doClose(self):
|
385
|
-
"""Forward the close button to the default close method."""
|
386
|
-
self.close()
|
378
|
+
preview = QPrintPreviewDialog(self)
|
379
|
+
preview.paintRequested.connect(self.docPreview.printPreview)
|
380
|
+
preview.exec_()
|
387
381
|
return
|
388
382
|
|
389
383
|
##
|
390
384
|
# Internal Functions
|
391
385
|
##
|
392
386
|
|
393
|
-
def _updatePreview(self, data: dict, build: BuildSettings):
|
387
|
+
def _updatePreview(self, data: dict, build: BuildSettings) -> None:
|
394
388
|
"""Update the preview widget and set relevant values."""
|
395
389
|
self.docPreview.setContent(data)
|
396
390
|
self.docPreview.setBuildName(build.name)
|
@@ -415,10 +409,8 @@ class GuiManuscript(QDialog):
|
|
415
409
|
return build
|
416
410
|
return None
|
417
411
|
|
418
|
-
def _saveSettings(self):
|
412
|
+
def _saveSettings(self) -> None:
|
419
413
|
"""Save the user GUI settings."""
|
420
|
-
logger.debug("Saving GuiManuscript settings")
|
421
|
-
|
422
414
|
buildOrder = []
|
423
415
|
for i in range(self.buildList.count()):
|
424
416
|
if item := self.buildList.item(i):
|
@@ -442,6 +434,7 @@ class GuiManuscript(QDialog):
|
|
442
434
|
detailsWidth = CONFIG.rpxInt(self.buildDetails.getColumnWidth())
|
443
435
|
detailsExpanded = self.buildDetails.getExpandedState()
|
444
436
|
|
437
|
+
logger.debug("Saving State: GuiManuscript")
|
445
438
|
pOptions = SHARED.project.options
|
446
439
|
pOptions.setValue("GuiManuscript", "winWidth", winWidth)
|
447
440
|
pOptions.setValue("GuiManuscript", "winHeight", winHeight)
|
@@ -455,7 +448,7 @@ class GuiManuscript(QDialog):
|
|
455
448
|
|
456
449
|
return
|
457
450
|
|
458
|
-
def _openSettingsDialog(self, build: BuildSettings):
|
451
|
+
def _openSettingsDialog(self, build: BuildSettings) -> None:
|
459
452
|
"""Open the build settings dialog."""
|
460
453
|
for obj in self.mainGui.children():
|
461
454
|
# Don't open a second dialog if one exists
|
@@ -476,7 +469,7 @@ class GuiManuscript(QDialog):
|
|
476
469
|
|
477
470
|
return
|
478
471
|
|
479
|
-
def _updateBuildsList(self):
|
472
|
+
def _updateBuildsList(self) -> None:
|
480
473
|
"""Update the list of available builds."""
|
481
474
|
self.buildList.clear()
|
482
475
|
for key, name in self._builds.builds():
|
@@ -488,7 +481,7 @@ class GuiManuscript(QDialog):
|
|
488
481
|
self._buildMap[key] = bItem
|
489
482
|
return
|
490
483
|
|
491
|
-
def _updateBuildItem(self, build: BuildSettings):
|
484
|
+
def _updateBuildItem(self, build: BuildSettings) -> None:
|
492
485
|
"""Update the entry of a specific build item."""
|
493
486
|
bItem = self._buildMap.get(build.buildID, None)
|
494
487
|
if isinstance(bItem, QListWidgetItem):
|
@@ -611,7 +604,7 @@ class _DetailsWidget(QWidget):
|
|
611
604
|
for key in entries:
|
612
605
|
sub = QTreeWidgetItem()
|
613
606
|
sub.setText(0, build.getLabel(key))
|
614
|
-
sub.setText(1, hFmt.apply(build.getStr(key), title))
|
607
|
+
sub.setText(1, hFmt.apply(build.getStr(key), title, 0))
|
615
608
|
item.addChild(sub)
|
616
609
|
for key in ["headings.hideScene", "headings.hideSection"]:
|
617
610
|
sub = QTreeWidgetItem()
|
@@ -778,8 +771,8 @@ class _PreviewWidget(QTextBrowser):
|
|
778
771
|
self.setHtml(html)
|
779
772
|
qApp.processEvents()
|
780
773
|
while self.find("!!tab!!"):
|
781
|
-
|
782
|
-
|
774
|
+
cursor = self.textCursor()
|
775
|
+
cursor.insertText("\t")
|
783
776
|
|
784
777
|
self.verticalScrollBar().setValue(sPos)
|
785
778
|
self._docTime = checkInt(data.get("time"), 0)
|