novelWriter 2.4.3__py3-none-any.whl → 2.5__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.4.3.dist-info → novelWriter-2.5.dist-info}/METADATA +4 -5
- {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/RECORD +122 -112
- {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +33 -39
- 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_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/i18n/project_pl_PL.json +116 -0
- novelwriter/assets/i18n/project_pt_BR.json +74 -74
- novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
- novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +2 -0
- novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
- novelwriter/assets/syntax/default_dark.conf +32 -18
- novelwriter/assets/syntax/default_light.conf +24 -10
- novelwriter/assets/syntax/dracula.conf +44 -0
- novelwriter/assets/syntax/grey_dark.conf +5 -4
- novelwriter/assets/syntax/grey_light.conf +5 -4
- novelwriter/assets/syntax/light_owl.conf +7 -6
- novelwriter/assets/syntax/night_owl.conf +7 -6
- novelwriter/assets/syntax/snazzy.conf +42 -0
- novelwriter/assets/syntax/solarized_dark.conf +4 -3
- novelwriter/assets/syntax/solarized_light.conf +4 -3
- novelwriter/assets/syntax/tango.conf +27 -11
- novelwriter/assets/syntax/tomorrow.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night.conf +7 -6
- novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
- novelwriter/assets/text/credits_en.htm +52 -41
- novelwriter/assets/themes/cyberpunk_night.conf +3 -0
- novelwriter/assets/themes/default_dark.conf +2 -0
- novelwriter/assets/themes/default_light.conf +2 -0
- novelwriter/assets/themes/dracula.conf +48 -0
- novelwriter/assets/themes/solarized_dark.conf +2 -0
- novelwriter/assets/themes/solarized_light.conf +2 -0
- novelwriter/common.py +33 -12
- novelwriter/config.py +184 -98
- novelwriter/constants.py +47 -35
- novelwriter/core/buildsettings.py +68 -69
- novelwriter/core/coretools.py +5 -23
- novelwriter/core/docbuild.py +52 -40
- novelwriter/core/document.py +3 -5
- novelwriter/core/index.py +115 -45
- novelwriter/core/item.py +8 -19
- novelwriter/core/options.py +2 -4
- novelwriter/core/project.py +37 -61
- novelwriter/core/projectdata.py +1 -3
- novelwriter/core/projectxml.py +12 -15
- novelwriter/core/sessions.py +3 -5
- novelwriter/core/spellcheck.py +4 -9
- novelwriter/core/status.py +211 -164
- novelwriter/core/storage.py +0 -8
- novelwriter/core/tohtml.py +139 -105
- novelwriter/core/tokenizer.py +278 -122
- novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
- novelwriter/core/toodt.py +257 -166
- novelwriter/core/toqdoc.py +419 -0
- novelwriter/core/tree.py +5 -7
- novelwriter/dialogs/about.py +11 -18
- novelwriter/dialogs/docmerge.py +17 -19
- novelwriter/dialogs/docsplit.py +17 -19
- novelwriter/dialogs/editlabel.py +6 -10
- novelwriter/dialogs/preferences.py +200 -164
- novelwriter/dialogs/projectsettings.py +225 -189
- novelwriter/dialogs/quotes.py +12 -9
- novelwriter/dialogs/wordlist.py +9 -15
- novelwriter/enum.py +35 -30
- novelwriter/error.py +8 -15
- novelwriter/extensions/configlayout.py +55 -21
- novelwriter/extensions/eventfilters.py +1 -5
- novelwriter/extensions/modified.py +70 -14
- novelwriter/extensions/novelselector.py +1 -3
- novelwriter/extensions/pagedsidebar.py +9 -12
- novelwriter/extensions/{circularprogress.py → progressbars.py} +30 -8
- novelwriter/extensions/statusled.py +40 -26
- novelwriter/extensions/switch.py +4 -6
- novelwriter/extensions/switchbox.py +7 -6
- novelwriter/extensions/versioninfo.py +3 -9
- novelwriter/gui/doceditor.py +120 -139
- novelwriter/gui/dochighlight.py +231 -186
- novelwriter/gui/docviewer.py +69 -108
- novelwriter/gui/docviewerpanel.py +3 -10
- novelwriter/gui/editordocument.py +1 -3
- novelwriter/gui/itemdetails.py +7 -11
- novelwriter/gui/mainmenu.py +22 -18
- novelwriter/gui/noveltree.py +11 -24
- novelwriter/gui/outline.py +15 -26
- novelwriter/gui/projtree.py +39 -65
- novelwriter/gui/search.py +10 -3
- novelwriter/gui/sidebar.py +2 -6
- novelwriter/gui/statusbar.py +29 -37
- novelwriter/gui/theme.py +26 -48
- novelwriter/guimain.py +162 -160
- novelwriter/shared.py +36 -19
- novelwriter/text/patterns.py +113 -0
- novelwriter/tools/dictionaries.py +10 -20
- novelwriter/tools/lipsum.py +10 -16
- novelwriter/tools/manusbuild.py +9 -11
- novelwriter/tools/manuscript.py +75 -149
- novelwriter/tools/manussettings.py +74 -76
- novelwriter/tools/noveldetails.py +16 -21
- novelwriter/tools/welcome.py +21 -26
- novelwriter/tools/writingstats.py +9 -12
- novelwriter/types.py +49 -4
- novelwriter/extensions/simpleprogress.py +0 -55
- {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/top_level.txt +0 -0
novelwriter/shared.py
CHANGED
@@ -31,7 +31,8 @@ from time import time
|
|
31
31
|
from typing import TYPE_CHECKING, TypeVar
|
32
32
|
|
33
33
|
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal
|
34
|
-
from PyQt5.
|
34
|
+
from PyQt5.QtGui import QFont
|
35
|
+
from PyQt5.QtWidgets import QFileDialog, QFontDialog, QMessageBox, QWidget
|
35
36
|
|
36
37
|
from novelwriter.common import formatFileFilter
|
37
38
|
from novelwriter.constants import nwFiles
|
@@ -171,6 +172,23 @@ class SharedData(QObject):
|
|
171
172
|
logger.debug("Thread Pool Max Count: %d", QThreadPool.globalInstance().maxThreadCount())
|
172
173
|
return
|
173
174
|
|
175
|
+
def closeEditor(self, tHandle: str | None = None) -> None:
|
176
|
+
"""Close the document editor, optionally a specific document."""
|
177
|
+
if tHandle is None or tHandle == self.mainGui.docEditor.docHandle:
|
178
|
+
self.mainGui.closeDocument()
|
179
|
+
return
|
180
|
+
|
181
|
+
def saveEditor(self, tHandle: str | None = None) -> None:
|
182
|
+
"""Save the editor content, optionally a specific document."""
|
183
|
+
docEditor = self.mainGui.docEditor
|
184
|
+
if (
|
185
|
+
self.hasProject and docEditor.docHandle
|
186
|
+
and (tHandle is None or tHandle == docEditor.docHandle)
|
187
|
+
):
|
188
|
+
logger.debug("Saving editor document before action")
|
189
|
+
docEditor.saveText()
|
190
|
+
return
|
191
|
+
|
174
192
|
def openProject(self, path: str | Path, clearLock: bool = False) -> bool:
|
175
193
|
"""Open a project."""
|
176
194
|
if self.project.isValid:
|
@@ -198,7 +216,7 @@ class SharedData(QObject):
|
|
198
216
|
|
199
217
|
def closeProject(self) -> None:
|
200
218
|
"""Close the current project."""
|
201
|
-
self.
|
219
|
+
self._closeToolDialogs()
|
202
220
|
self.project.closeProject(self._idleTime)
|
203
221
|
self._resetProject()
|
204
222
|
self._resetIdleTimer()
|
@@ -244,8 +262,11 @@ class SharedData(QObject):
|
|
244
262
|
QThreadPool.globalInstance().start(runnable, priority=priority)
|
245
263
|
return
|
246
264
|
|
247
|
-
def getProjectPath(
|
248
|
-
|
265
|
+
def getProjectPath(
|
266
|
+
self, parent: QWidget,
|
267
|
+
path: str | Path | None = None,
|
268
|
+
allowZip: bool = False
|
269
|
+
) -> Path | None:
|
249
270
|
"""Open the file dialog and select a novelWriter project file."""
|
250
271
|
label = (self.tr("novelWriter Project File or Zip File")
|
251
272
|
if allowZip else self.tr("novelWriter Project File"))
|
@@ -256,6 +277,13 @@ class SharedData(QObject):
|
|
256
277
|
)
|
257
278
|
return Path(selected) if selected else None
|
258
279
|
|
280
|
+
def getFont(self, current: QFont, native: bool) -> tuple[QFont, bool]:
|
281
|
+
"""Open the font dialog and select a font."""
|
282
|
+
kwargs = {}
|
283
|
+
if not native:
|
284
|
+
kwargs["options"] = QFontDialog.FontDialogOption.DontUseNativeDialog
|
285
|
+
return QFontDialog.getFont(current, self.mainGui, self.tr("Select Font"), **kwargs)
|
286
|
+
|
259
287
|
def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
|
260
288
|
"""Find a top level widget."""
|
261
289
|
for widget in self.mainGui.children():
|
@@ -294,7 +322,6 @@ class SharedData(QObject):
|
|
294
322
|
if log:
|
295
323
|
logger.info(self._lastAlert, stacklevel=2)
|
296
324
|
alert.exec()
|
297
|
-
alert.deleteLater()
|
298
325
|
return
|
299
326
|
|
300
327
|
def warn(self, text: str, info: str = "", details: str = "", log: bool = True) -> None:
|
@@ -306,7 +333,6 @@ class SharedData(QObject):
|
|
306
333
|
if log:
|
307
334
|
logger.warning(self._lastAlert, stacklevel=2)
|
308
335
|
alert.exec()
|
309
|
-
alert.deleteLater()
|
310
336
|
return
|
311
337
|
|
312
338
|
def error(self, text: str, info: str = "", details: str = "", log: bool = True,
|
@@ -321,7 +347,6 @@ class SharedData(QObject):
|
|
321
347
|
if log:
|
322
348
|
logger.error(self._lastAlert, stacklevel=2)
|
323
349
|
alert.exec()
|
324
|
-
alert.deleteLater()
|
325
350
|
return
|
326
351
|
|
327
352
|
def question(self, text: str, info: str = "", details: str = "", warn: bool = False) -> bool:
|
@@ -332,7 +357,6 @@ class SharedData(QObject):
|
|
332
357
|
self._lastAlert = alert.logMessage
|
333
358
|
alert.exec()
|
334
359
|
isYes = alert.result() == QMessageBox.StandardButton.Yes
|
335
|
-
alert.deleteLater()
|
336
360
|
return isYes
|
337
361
|
|
338
362
|
##
|
@@ -357,19 +381,14 @@ class SharedData(QObject):
|
|
357
381
|
self._idleTime = 0.0
|
358
382
|
return
|
359
383
|
|
360
|
-
def
|
361
|
-
"""Close
|
362
|
-
from novelwriter.
|
363
|
-
from novelwriter.tools.writingstats import GuiWritingStats
|
364
|
-
|
384
|
+
def _closeToolDialogs(self) -> None:
|
385
|
+
"""Close all open tool dialogs."""
|
386
|
+
from novelwriter.extensions.modified import NToolDialog
|
365
387
|
for widget in self.mainGui.children():
|
366
|
-
if isinstance(widget,
|
388
|
+
if isinstance(widget, NToolDialog):
|
367
389
|
widget.close()
|
368
|
-
|
369
390
|
return
|
370
391
|
|
371
|
-
# END Class SharedData
|
372
|
-
|
373
392
|
|
374
393
|
class _GuiAlert(QMessageBox):
|
375
394
|
|
@@ -430,5 +449,3 @@ class _GuiAlert(QMessageBox):
|
|
430
449
|
self.setIconPixmap(self._theme.getPixmap("alert_question", (pSz, pSz)))
|
431
450
|
self.setWindowTitle(self.tr("Question"))
|
432
451
|
return
|
433
|
-
|
434
|
-
# END Class _GuiAlert
|
@@ -0,0 +1,113 @@
|
|
1
|
+
"""
|
2
|
+
novelWriter – Text Pattern Functions
|
3
|
+
====================================
|
4
|
+
|
5
|
+
File History:
|
6
|
+
Created: 2024-06-01 [2.5ec1]
|
7
|
+
|
8
|
+
This file is a part of novelWriter
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
|
+
|
11
|
+
This program is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful, but
|
17
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
19
|
+
General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
23
|
+
"""
|
24
|
+
from __future__ import annotations
|
25
|
+
|
26
|
+
from PyQt5.QtCore import QRegularExpression
|
27
|
+
|
28
|
+
from novelwriter import CONFIG
|
29
|
+
from novelwriter.constants import nwRegEx
|
30
|
+
from novelwriter.types import QRegExUnicode
|
31
|
+
|
32
|
+
|
33
|
+
class RegExPatterns:
|
34
|
+
|
35
|
+
@property
|
36
|
+
def markdownItalic(self) -> QRegularExpression:
|
37
|
+
"""Markdown italic style."""
|
38
|
+
rxRule = QRegularExpression(nwRegEx.FMT_EI)
|
39
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
40
|
+
return rxRule
|
41
|
+
|
42
|
+
@property
|
43
|
+
def markdownBold(self) -> QRegularExpression:
|
44
|
+
"""Markdown bold style."""
|
45
|
+
rxRule = QRegularExpression(nwRegEx.FMT_EB)
|
46
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
47
|
+
return rxRule
|
48
|
+
|
49
|
+
@property
|
50
|
+
def markdownStrike(self) -> QRegularExpression:
|
51
|
+
"""Markdown strikethrough style."""
|
52
|
+
rxRule = QRegularExpression(nwRegEx.FMT_ST)
|
53
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
54
|
+
return rxRule
|
55
|
+
|
56
|
+
@property
|
57
|
+
def shortcodePlain(self) -> QRegularExpression:
|
58
|
+
"""Plain shortcode style."""
|
59
|
+
rxRule = QRegularExpression(nwRegEx.FMT_SC)
|
60
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
61
|
+
return rxRule
|
62
|
+
|
63
|
+
@property
|
64
|
+
def shortcodeValue(self) -> QRegularExpression:
|
65
|
+
"""Plain shortcode style."""
|
66
|
+
rxRule = QRegularExpression(nwRegEx.FMT_SV)
|
67
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
68
|
+
return rxRule
|
69
|
+
|
70
|
+
@property
|
71
|
+
def dialogStyle(self) -> QRegularExpression:
|
72
|
+
"""Dialogue detection rule based on user settings."""
|
73
|
+
symO = ""
|
74
|
+
symC = ""
|
75
|
+
if CONFIG.dialogStyle in (1, 3):
|
76
|
+
symO += CONFIG.fmtSQuoteOpen
|
77
|
+
symC += CONFIG.fmtSQuoteClose
|
78
|
+
if CONFIG.dialogStyle in (2, 3):
|
79
|
+
symO += CONFIG.fmtDQuoteOpen
|
80
|
+
symC += CONFIG.fmtDQuoteClose
|
81
|
+
|
82
|
+
rxEnd = "|$" if CONFIG.allowOpenDial else ""
|
83
|
+
rxRule = QRegularExpression(f"\\B[{symO}].*?(?:[{symC}]\\B{rxEnd})")
|
84
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
85
|
+
return rxRule
|
86
|
+
|
87
|
+
@property
|
88
|
+
def dialogLine(self) -> QRegularExpression:
|
89
|
+
"""Dialogue line rule based on user settings."""
|
90
|
+
sym = QRegularExpression.escape(CONFIG.dialogLine)
|
91
|
+
rxRule = QRegularExpression(f"^{sym}.*?$")
|
92
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
93
|
+
return rxRule
|
94
|
+
|
95
|
+
@property
|
96
|
+
def narratorBreak(self) -> QRegularExpression:
|
97
|
+
"""Dialogue narrator break rule based on user settings."""
|
98
|
+
sym = QRegularExpression.escape(CONFIG.narratorBreak)
|
99
|
+
rxRule = QRegularExpression(f"\\B{sym}\\S.*?\\S{sym}\\B")
|
100
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
101
|
+
return rxRule
|
102
|
+
|
103
|
+
@property
|
104
|
+
def altDialogStyle(self) -> QRegularExpression:
|
105
|
+
"""Dialogue alternative rule based on user settings."""
|
106
|
+
symO = QRegularExpression.escape(CONFIG.altDialogOpen)
|
107
|
+
symC = QRegularExpression.escape(CONFIG.altDialogClose)
|
108
|
+
rxRule = QRegularExpression(f"\\B{symO}.*?{symC}\\B")
|
109
|
+
rxRule.setPatternOptions(QRegExUnicode)
|
110
|
+
return rxRule
|
111
|
+
|
112
|
+
|
113
|
+
REGEX_PATTERNS = RegExPatterns()
|
@@ -31,20 +31,20 @@ from zipfile import ZipFile
|
|
31
31
|
from PyQt5.QtCore import pyqtSlot
|
32
32
|
from PyQt5.QtGui import QCloseEvent, QTextCursor
|
33
33
|
from PyQt5.QtWidgets import (
|
34
|
-
QApplication,
|
35
|
-
|
34
|
+
QApplication, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel,
|
35
|
+
QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
|
36
36
|
)
|
37
37
|
|
38
38
|
from novelwriter import CONFIG, SHARED
|
39
|
-
from novelwriter.common import formatFileFilter, formatInt, getFileSize, openExternalPath
|
39
|
+
from novelwriter.common import cssCol, formatFileFilter, formatInt, getFileSize, openExternalPath
|
40
40
|
from novelwriter.error import formatException
|
41
|
-
from novelwriter.extensions.modified import NIconToolButton
|
41
|
+
from novelwriter.extensions.modified import NIconToolButton, NNonBlockingDialog
|
42
42
|
from novelwriter.types import QtDialogClose
|
43
43
|
|
44
44
|
logger = logging.getLogger(__name__)
|
45
45
|
|
46
46
|
|
47
|
-
class GuiDictionaries(
|
47
|
+
class GuiDictionaries(NNonBlockingDialog):
|
48
48
|
|
49
49
|
def __init__(self, parent: QWidget) -> None:
|
50
50
|
super().__init__(parent=parent)
|
@@ -109,7 +109,7 @@ class GuiDictionaries(QDialog):
|
|
109
109
|
|
110
110
|
# Buttons
|
111
111
|
self.buttonBox = QDialogButtonBox(QtDialogClose, self)
|
112
|
-
self.buttonBox.rejected.connect(self.
|
112
|
+
self.buttonBox.rejected.connect(self.reject)
|
113
113
|
|
114
114
|
# Assemble
|
115
115
|
self.innerBox = QVBoxLayout()
|
@@ -172,7 +172,7 @@ class GuiDictionaries(QDialog):
|
|
172
172
|
def closeEvent(self, event: QCloseEvent) -> None:
|
173
173
|
"""Capture the user closing the window."""
|
174
174
|
event.accept()
|
175
|
-
self.
|
175
|
+
self.softDelete()
|
176
176
|
return
|
177
177
|
|
178
178
|
##
|
@@ -186,7 +186,7 @@ class GuiDictionaries(QDialog):
|
|
186
186
|
(self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
|
187
187
|
])
|
188
188
|
soxFile, _ = QFileDialog.getOpenFileName(
|
189
|
-
self, self.tr("Browse Files"),
|
189
|
+
self, self.tr("Browse Files"), str(CONFIG.homePath()), filter=ffilter
|
190
190
|
)
|
191
191
|
if soxFile:
|
192
192
|
path = Path(soxFile).absolute()
|
@@ -220,12 +220,6 @@ class GuiDictionaries(QDialog):
|
|
220
220
|
SHARED.error("Path not found.")
|
221
221
|
return
|
222
222
|
|
223
|
-
@pyqtSlot()
|
224
|
-
def _doClose(self) -> None:
|
225
|
-
"""Close the dialog."""
|
226
|
-
self.close()
|
227
|
-
return
|
228
|
-
|
229
223
|
##
|
230
224
|
# Internal Functions
|
231
225
|
##
|
@@ -257,13 +251,9 @@ class GuiDictionaries(QDialog):
|
|
257
251
|
cursor.movePosition(QTextCursor.MoveOperation.End)
|
258
252
|
if cursor.position() > 0:
|
259
253
|
cursor.insertText("\n")
|
260
|
-
if err
|
261
|
-
|
262
|
-
else:
|
263
|
-
cursor.insertText(text)
|
254
|
+
textCol = cssCol(SHARED.theme.errorText if err else self.palette().text().color())
|
255
|
+
cursor.insertHtml(f"<font style='color: {textCol}'>{text}</font>")
|
264
256
|
cursor.movePosition(QTextCursor.MoveOperation.End)
|
265
257
|
cursor.deleteChar()
|
266
258
|
self.infoBox.setTextCursor(cursor)
|
267
259
|
return
|
268
|
-
|
269
|
-
# END Class GuiDictionaries
|
novelwriter/tools/lipsum.py
CHANGED
@@ -23,37 +23,35 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
23
|
"""
|
24
24
|
from __future__ import annotations
|
25
25
|
|
26
|
-
import random
|
27
26
|
import logging
|
27
|
+
import random
|
28
28
|
|
29
|
-
from PyQt5.QtCore import
|
29
|
+
from PyQt5.QtCore import pyqtSlot
|
30
30
|
from PyQt5.QtWidgets import (
|
31
|
-
|
32
|
-
|
31
|
+
QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel, QSpinBox, QVBoxLayout,
|
32
|
+
QWidget
|
33
33
|
)
|
34
34
|
|
35
35
|
from novelwriter import CONFIG, SHARED
|
36
36
|
from novelwriter.common import readTextFile
|
37
|
+
from novelwriter.extensions.modified import NDialog
|
37
38
|
from novelwriter.extensions.switch import NSwitch
|
38
|
-
from novelwriter.types import QtAlignLeft, QtAlignRight,
|
39
|
+
from novelwriter.types import QtAlignLeft, QtAlignRight, QtDialogClose, QtRoleAction
|
39
40
|
|
40
41
|
logger = logging.getLogger(__name__)
|
41
42
|
|
42
43
|
|
43
|
-
class GuiLipsum(
|
44
|
+
class GuiLipsum(NDialog):
|
44
45
|
|
45
46
|
def __init__(self, parent: QWidget) -> None:
|
46
47
|
super().__init__(parent=parent)
|
47
48
|
|
48
49
|
logger.debug("Create: GuiLipsum")
|
49
50
|
self.setObjectName("GuiLipsum")
|
50
|
-
|
51
|
-
self.setWindowFlag(Qt.WindowType.Tool)
|
51
|
+
self.setWindowTitle(self.tr("Insert Placeholder Text"))
|
52
52
|
|
53
53
|
self._lipsumText = ""
|
54
54
|
|
55
|
-
self.setWindowTitle(self.tr("Insert Placeholder Text"))
|
56
|
-
|
57
55
|
vSp = CONFIG.pxInt(4)
|
58
56
|
nPx = CONFIG.pxInt(64)
|
59
57
|
|
@@ -95,7 +93,7 @@ class GuiLipsum(QDialog):
|
|
95
93
|
|
96
94
|
# Buttons
|
97
95
|
self.buttonBox = QDialogButtonBox(self)
|
98
|
-
self.buttonBox.rejected.connect(self.
|
96
|
+
self.buttonBox.rejected.connect(self.reject)
|
99
97
|
|
100
98
|
self.btnClose = self.buttonBox.addButton(QtDialogClose)
|
101
99
|
self.btnClose.setAutoDefault(False)
|
@@ -104,8 +102,6 @@ class GuiLipsum(QDialog):
|
|
104
102
|
self.btnInsert.clicked.connect(self._doInsert)
|
105
103
|
self.btnInsert.setAutoDefault(False)
|
106
104
|
|
107
|
-
self.rejected.connect(self.close)
|
108
|
-
|
109
105
|
# Assemble
|
110
106
|
self.outerBox = QVBoxLayout()
|
111
107
|
self.outerBox.addLayout(self.innerBox)
|
@@ -132,7 +128,7 @@ class GuiLipsum(QDialog):
|
|
132
128
|
cls = GuiLipsum(parent)
|
133
129
|
cls.exec()
|
134
130
|
text = cls.lipsumText
|
135
|
-
cls.
|
131
|
+
cls.softDelete()
|
136
132
|
return text
|
137
133
|
|
138
134
|
##
|
@@ -150,5 +146,3 @@ class GuiLipsum(QDialog):
|
|
150
146
|
self._lipsumText = "\n\n".join(lipsumText[0:pCount]) + "\n\n"
|
151
147
|
self.close()
|
152
148
|
return
|
153
|
-
|
154
|
-
# END Class GuiLipsum
|
novelwriter/tools/manusbuild.py
CHANGED
@@ -30,7 +30,7 @@ from pathlib import Path
|
|
30
30
|
from PyQt5.QtCore import QTimer, pyqtSlot
|
31
31
|
from PyQt5.QtGui import QCloseEvent
|
32
32
|
from PyQt5.QtWidgets import (
|
33
|
-
QAbstractButton, QAbstractItemView,
|
33
|
+
QAbstractButton, QAbstractItemView, QDialogButtonBox, QFileDialog,
|
34
34
|
QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem,
|
35
35
|
QPushButton, QSplitter, QVBoxLayout, QWidget
|
36
36
|
)
|
@@ -42,14 +42,14 @@ from novelwriter.core.buildsettings import BuildSettings
|
|
42
42
|
from novelwriter.core.docbuild import NWBuildDocument
|
43
43
|
from novelwriter.core.item import NWItem
|
44
44
|
from novelwriter.enum import nwBuildFmt
|
45
|
-
from novelwriter.extensions.modified import NIconToolButton
|
46
|
-
from novelwriter.extensions.
|
45
|
+
from novelwriter.extensions.modified import NDialog, NIconToolButton
|
46
|
+
from novelwriter.extensions.progressbars import NProgressSimple
|
47
47
|
from novelwriter.types import QtAlignCenter, QtDialogClose, QtRoleAction, QtRoleReject, QtUserRole
|
48
48
|
|
49
49
|
logger = logging.getLogger(__name__)
|
50
50
|
|
51
51
|
|
52
|
-
class GuiManuscriptBuild(
|
52
|
+
class GuiManuscriptBuild(NDialog):
|
53
53
|
"""GUI Tools: Manuscript Build Dialog
|
54
54
|
|
55
55
|
This is the tool for running the build itself. It can be accessed
|
@@ -220,7 +220,7 @@ class GuiManuscriptBuild(QDialog):
|
|
220
220
|
|
221
221
|
self.btnBuild.setFocus()
|
222
222
|
self._populateContentList()
|
223
|
-
self.buildPath.setText(str(self._build.
|
223
|
+
self.buildPath.setText(str(self._build.lastBuildPath))
|
224
224
|
if self._build.lastBuildName:
|
225
225
|
self.buildName.setText(self._build.lastBuildName)
|
226
226
|
else:
|
@@ -250,7 +250,7 @@ class GuiManuscriptBuild(QDialog):
|
|
250
250
|
"""
|
251
251
|
self._saveSettings()
|
252
252
|
event.accept()
|
253
|
-
self.
|
253
|
+
self.softDelete()
|
254
254
|
return
|
255
255
|
|
256
256
|
##
|
@@ -274,7 +274,7 @@ class GuiManuscriptBuild(QDialog):
|
|
274
274
|
def _doSelectPath(self) -> None:
|
275
275
|
"""Select a folder for output."""
|
276
276
|
bPath = Path(self.buildPath.text())
|
277
|
-
bPath = bPath if bPath.is_dir() else self._build.
|
277
|
+
bPath = bPath if bPath.is_dir() else self._build.lastBuildPath
|
278
278
|
savePath = QFileDialog.getExistingDirectory(
|
279
279
|
self, self.tr("Select Folder"), str(bPath)
|
280
280
|
)
|
@@ -327,7 +327,7 @@ class GuiManuscriptBuild(QDialog):
|
|
327
327
|
return False
|
328
328
|
|
329
329
|
# Make sure editor content is saved before we start
|
330
|
-
SHARED.
|
330
|
+
SHARED.saveEditor()
|
331
331
|
|
332
332
|
docBuild = NWBuildDocument(SHARED.project, self._build)
|
333
333
|
docBuild.queueAll()
|
@@ -336,7 +336,7 @@ class GuiManuscriptBuild(QDialog):
|
|
336
336
|
for i, _ in docBuild.iterBuild(buildPath, bFormat):
|
337
337
|
self.buildProgress.setValue(i+1)
|
338
338
|
|
339
|
-
self._build.
|
339
|
+
self._build.setLastBuildPath(bPath)
|
340
340
|
self._build.setLastBuildName(bName)
|
341
341
|
self._build.setLastFormat(bFormat)
|
342
342
|
|
@@ -403,5 +403,3 @@ class GuiManuscriptBuild(QDialog):
|
|
403
403
|
"""Open the build folder in the system's file explorer."""
|
404
404
|
openExternalPath(Path(self.buildPath.text()))
|
405
405
|
return
|
406
|
-
|
407
|
-
# END Class GuiManuscriptBuild
|