novelWriter 2.4b1__py3-none-any.whl → 2.4.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.4b1.dist-info → novelWriter-2.4.1.dist-info}/METADATA +5 -6
- {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/RECORD +79 -83
- novelwriter/__init__.py +15 -8
- 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_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/icons/none.svg +4 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
- novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +2 -2
- novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/common.py +11 -3
- novelwriter/config.py +12 -4
- novelwriter/core/buildsettings.py +7 -7
- novelwriter/core/coretools.py +21 -22
- novelwriter/core/docbuild.py +2 -2
- novelwriter/core/projectxml.py +1 -1
- novelwriter/core/spellcheck.py +3 -3
- novelwriter/core/status.py +3 -2
- novelwriter/core/tokenizer.py +3 -3
- novelwriter/core/toodt.py +333 -356
- novelwriter/dialogs/about.py +9 -11
- novelwriter/dialogs/docmerge.py +17 -14
- novelwriter/dialogs/docsplit.py +14 -12
- novelwriter/dialogs/editlabel.py +5 -4
- novelwriter/dialogs/preferences.py +29 -34
- novelwriter/dialogs/projectsettings.py +31 -28
- novelwriter/dialogs/quotes.py +10 -9
- novelwriter/dialogs/wordlist.py +17 -14
- novelwriter/error.py +14 -12
- novelwriter/extensions/circularprogress.py +12 -8
- novelwriter/extensions/configlayout.py +1 -3
- novelwriter/extensions/modified.py +33 -2
- novelwriter/extensions/pagedsidebar.py +16 -14
- novelwriter/extensions/simpleprogress.py +3 -1
- novelwriter/extensions/statusled.py +3 -1
- novelwriter/extensions/switch.py +10 -9
- novelwriter/extensions/switchbox.py +14 -13
- novelwriter/gui/doceditor.py +205 -246
- novelwriter/gui/dochighlight.py +26 -9
- novelwriter/gui/docviewer.py +55 -59
- novelwriter/gui/docviewerpanel.py +16 -13
- novelwriter/gui/editordocument.py +4 -4
- novelwriter/gui/itemdetails.py +45 -48
- novelwriter/gui/mainmenu.py +2 -2
- novelwriter/gui/noveltree.py +23 -21
- novelwriter/gui/outline.py +93 -94
- novelwriter/gui/projtree.py +32 -30
- novelwriter/gui/search.py +75 -29
- novelwriter/gui/sidebar.py +24 -28
- novelwriter/gui/statusbar.py +14 -14
- novelwriter/gui/theme.py +61 -39
- novelwriter/guimain.py +37 -33
- novelwriter/shared.py +21 -9
- novelwriter/text/counting.py +1 -0
- novelwriter/tools/dictionaries.py +15 -14
- novelwriter/tools/lipsum.py +20 -17
- novelwriter/tools/manusbuild.py +44 -35
- novelwriter/tools/manuscript.py +112 -112
- novelwriter/tools/manussettings.py +91 -98
- novelwriter/tools/noveldetails.py +20 -18
- novelwriter/tools/welcome.py +51 -48
- novelwriter/tools/writingstats.py +61 -55
- novelwriter/types.py +90 -0
- novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
- novelwriter/core/__init__.py +0 -3
- novelwriter/dialogs/__init__.py +0 -3
- novelwriter/extensions/__init__.py +0 -3
- novelwriter/gui/__init__.py +0 -3
- novelwriter/text/__init__.py +0 -3
- novelwriter/tools/__init__.py +0 -3
- {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/WHEEL +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/top_level.txt +0 -0
novelwriter/tools/manuscript.py
CHANGED
@@ -26,19 +26,19 @@ from __future__ import annotations
|
|
26
26
|
import json
|
27
27
|
import logging
|
28
28
|
|
29
|
+
from datetime import datetime
|
29
30
|
from time import time
|
30
31
|
from typing import TYPE_CHECKING
|
31
|
-
from datetime import datetime
|
32
32
|
|
33
|
+
from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
|
33
34
|
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
|
34
|
-
from PyQt5.
|
35
|
+
from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
|
35
36
|
from PyQt5.QtWidgets import (
|
36
|
-
QAbstractItemView, QDialog, QFormLayout, QGridLayout,
|
37
|
-
|
38
|
-
|
39
|
-
QVBoxLayout, QWidget
|
37
|
+
QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout,
|
38
|
+
QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton,
|
39
|
+
QSizePolicy, QSplitter, QStackedWidget, QTabWidget, QTextBrowser,
|
40
|
+
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
40
41
|
)
|
41
|
-
from PyQt5.QtPrintSupport import QPrintPreviewDialog, QPrinter
|
42
42
|
|
43
43
|
from novelwriter import CONFIG, SHARED
|
44
44
|
from novelwriter.common import checkInt, fuzzyTime
|
@@ -48,10 +48,14 @@ from novelwriter.core.tohtml import ToHtml
|
|
48
48
|
from novelwriter.core.tokenizer import HeadingFormatter
|
49
49
|
from novelwriter.error import logException
|
50
50
|
from novelwriter.extensions.circularprogress import NProgressCircle
|
51
|
-
from novelwriter.extensions.modified import NIconToolButton
|
51
|
+
from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
|
52
52
|
from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
|
53
53
|
from novelwriter.tools.manusbuild import GuiManuscriptBuild
|
54
54
|
from novelwriter.tools.manussettings import GuiBuildSettings
|
55
|
+
from novelwriter.types import (
|
56
|
+
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignRight, QtAlignTop,
|
57
|
+
QtUserRole
|
58
|
+
)
|
55
59
|
|
56
60
|
if TYPE_CHECKING: # pragma: no cover
|
57
61
|
from novelwriter.guimain import GuiMain
|
@@ -67,7 +71,7 @@ class GuiManuscript(QDialog):
|
|
67
71
|
a document directly to disk.
|
68
72
|
"""
|
69
73
|
|
70
|
-
D_KEY =
|
74
|
+
D_KEY = QtUserRole
|
71
75
|
|
72
76
|
def __init__(self, mainGui: GuiMain) -> None:
|
73
77
|
super().__init__(parent=mainGui)
|
@@ -86,7 +90,7 @@ class GuiManuscript(QDialog):
|
|
86
90
|
self.setMinimumWidth(CONFIG.pxInt(600))
|
87
91
|
self.setMinimumHeight(CONFIG.pxInt(500))
|
88
92
|
|
89
|
-
|
93
|
+
iSz = SHARED.theme.baseIconSize
|
90
94
|
wWin = CONFIG.pxInt(900)
|
91
95
|
hWin = CONFIG.pxInt(600)
|
92
96
|
|
@@ -100,30 +104,27 @@ class GuiManuscript(QDialog):
|
|
100
104
|
# ==============
|
101
105
|
|
102
106
|
qPalette = self.palette()
|
103
|
-
qPalette.setBrush(QPalette.Window, qPalette.base())
|
107
|
+
qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
|
104
108
|
self.setPalette(qPalette)
|
105
109
|
|
106
110
|
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
|
107
111
|
|
108
|
-
self.tbAdd = NIconToolButton(self,
|
109
|
-
self.tbAdd.setIcon(SHARED.theme.getIcon("add"))
|
112
|
+
self.tbAdd = NIconToolButton(self, iSz, "add")
|
110
113
|
self.tbAdd.setToolTip(self.tr("Add New Build"))
|
111
114
|
self.tbAdd.setStyleSheet(buttonStyle)
|
112
115
|
self.tbAdd.clicked.connect(self._createNewBuild)
|
113
116
|
|
114
|
-
self.tbDel = NIconToolButton(self,
|
115
|
-
self.tbDel.setIcon(SHARED.theme.getIcon("remove"))
|
117
|
+
self.tbDel = NIconToolButton(self, iSz, "remove")
|
116
118
|
self.tbDel.setToolTip(self.tr("Delete Selected Build"))
|
117
119
|
self.tbDel.setStyleSheet(buttonStyle)
|
118
120
|
self.tbDel.clicked.connect(self._deleteSelectedBuild)
|
119
121
|
|
120
|
-
self.tbEdit = NIconToolButton(self,
|
121
|
-
self.tbEdit.setIcon(SHARED.theme.getIcon("edit"))
|
122
|
+
self.tbEdit = NIconToolButton(self, iSz, "edit")
|
122
123
|
self.tbEdit.setToolTip(self.tr("Edit Selected Build"))
|
123
124
|
self.tbEdit.setStyleSheet(buttonStyle)
|
124
125
|
self.tbEdit.clicked.connect(self._editSelectedBuild)
|
125
126
|
|
126
|
-
self.lblBuilds = QLabel("<b>{0}</b>".format(self.tr("Builds")))
|
127
|
+
self.lblBuilds = QLabel("<b>{0}</b>".format(self.tr("Builds")), self)
|
127
128
|
|
128
129
|
self.listToolBox = QHBoxLayout()
|
129
130
|
self.listToolBox.addWidget(self.lblBuilds)
|
@@ -137,11 +138,11 @@ class GuiManuscript(QDialog):
|
|
137
138
|
# ======
|
138
139
|
|
139
140
|
self.buildList = QListWidget(self)
|
140
|
-
self.buildList.setIconSize(
|
141
|
+
self.buildList.setIconSize(iSz)
|
141
142
|
self.buildList.doubleClicked.connect(self._editSelectedBuild)
|
142
143
|
self.buildList.currentItemChanged.connect(self._updateBuildDetails)
|
143
|
-
self.buildList.setSelectionMode(QAbstractItemView.SingleSelection)
|
144
|
-
self.buildList.setDragDropMode(QAbstractItemView.InternalMove)
|
144
|
+
self.buildList.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
145
|
+
self.buildList.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
145
146
|
|
146
147
|
# Details Tabs
|
147
148
|
# ============
|
@@ -154,7 +155,7 @@ class GuiManuscript(QDialog):
|
|
154
155
|
self.buildOutline = _OutlineWidget(self)
|
155
156
|
|
156
157
|
self.detailsTabs = QTabWidget(self)
|
157
|
-
self.detailsTabs.addTab(self.buildDetails, self.tr("
|
158
|
+
self.detailsTabs.addTab(self.buildDetails, self.tr("Details"))
|
158
159
|
self.detailsTabs.addTab(self.buildOutline, self.tr("Outline"))
|
159
160
|
self.detailsTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
|
160
161
|
|
@@ -169,16 +170,16 @@ class GuiManuscript(QDialog):
|
|
169
170
|
# Process Controls
|
170
171
|
# ================
|
171
172
|
|
172
|
-
self.btnPreview = QPushButton(self.tr("Preview"))
|
173
|
+
self.btnPreview = QPushButton(self.tr("Preview"), self)
|
173
174
|
self.btnPreview.clicked.connect(self._generatePreview)
|
174
175
|
|
175
|
-
self.btnPrint = QPushButton(self.tr("Print"))
|
176
|
+
self.btnPrint = QPushButton(self.tr("Print"), self)
|
176
177
|
self.btnPrint.clicked.connect(self._printDocument)
|
177
178
|
|
178
|
-
self.btnBuild = QPushButton(self.tr("Build"))
|
179
|
+
self.btnBuild = QPushButton(self.tr("Build"), self)
|
179
180
|
self.btnBuild.clicked.connect(self._buildManuscript)
|
180
181
|
|
181
|
-
self.btnClose = QPushButton(self.tr("Close"))
|
182
|
+
self.btnClose = QPushButton(self.tr("Close"), self)
|
182
183
|
self.btnClose.clicked.connect(self.close)
|
183
184
|
|
184
185
|
self.processBox = QGridLayout()
|
@@ -210,7 +211,7 @@ class GuiManuscript(QDialog):
|
|
210
211
|
self.optsWidget = QWidget(self)
|
211
212
|
self.optsWidget.setLayout(self.controlBox)
|
212
213
|
|
213
|
-
self.mainSplit = QSplitter()
|
214
|
+
self.mainSplit = QSplitter(self)
|
214
215
|
self.mainSplit.addWidget(self.optsWidget)
|
215
216
|
self.mainSplit.addWidget(self.docWdiget)
|
216
217
|
self.mainSplit.setCollapsible(0, False)
|
@@ -302,26 +303,24 @@ class GuiManuscript(QDialog):
|
|
302
303
|
@pyqtSlot()
|
303
304
|
def _editSelectedBuild(self) -> None:
|
304
305
|
"""Edit the currently selected build settings entry."""
|
305
|
-
build
|
306
|
-
if build is not None:
|
306
|
+
if build := self._getSelectedBuild():
|
307
307
|
self._openSettingsDialog(build)
|
308
308
|
return
|
309
309
|
|
310
310
|
@pyqtSlot("QListWidgetItem*", "QListWidgetItem*")
|
311
311
|
def _updateBuildDetails(self, current: QListWidgetItem, previous: QListWidgetItem) -> None:
|
312
312
|
"""Process change of build selection to update the details."""
|
313
|
-
if
|
314
|
-
|
315
|
-
if build is not None:
|
316
|
-
self.buildDetails.updateInfo(build)
|
313
|
+
if current and (build := self._builds.getBuild(current.data(self.D_KEY))):
|
314
|
+
self.buildDetails.updateInfo(build)
|
317
315
|
return
|
318
316
|
|
319
317
|
@pyqtSlot()
|
320
318
|
def _deleteSelectedBuild(self) -> None:
|
321
319
|
"""Delete the currently selected build settings entry."""
|
322
|
-
build
|
323
|
-
if build is not None:
|
320
|
+
if build := self._getSelectedBuild():
|
324
321
|
if SHARED.question(self.tr("Delete build '{0}'?".format(build.name))):
|
322
|
+
if dialog := self._findSettingsDialog(build.buildID):
|
323
|
+
dialog.close()
|
325
324
|
self._builds.removeBuild(build.buildID)
|
326
325
|
self._updateBuildsList()
|
327
326
|
return
|
@@ -331,8 +330,7 @@ class GuiManuscript(QDialog):
|
|
331
330
|
"""Process new build settings from the settings dialog."""
|
332
331
|
self._builds.setBuild(build)
|
333
332
|
self._updateBuildItem(build)
|
334
|
-
current
|
335
|
-
if isinstance(current, QListWidgetItem) and current.data(self.D_KEY) == build.buildID:
|
333
|
+
if (current := self.buildList.currentItem()) and current.data(self.D_KEY) == build.buildID:
|
336
334
|
self._updateBuildDetails(current, current)
|
337
335
|
return
|
338
336
|
|
@@ -341,10 +339,12 @@ class GuiManuscript(QDialog):
|
|
341
339
|
"""Run the document builder on the current build settings for
|
342
340
|
the preview widget.
|
343
341
|
"""
|
344
|
-
build
|
345
|
-
if build is None:
|
342
|
+
if not (build := self._getSelectedBuild()):
|
346
343
|
return
|
347
344
|
|
345
|
+
# Make sure editor content is saved before we start
|
346
|
+
SHARED.mainGui.saveDocument()
|
347
|
+
|
348
348
|
docBuild = NWBuildDocument(SHARED.project, build)
|
349
349
|
docBuild.setPreviewMode(True)
|
350
350
|
docBuild.queueAll()
|
@@ -352,7 +352,7 @@ class GuiManuscript(QDialog):
|
|
352
352
|
self.docPreview.beginNewBuild(len(docBuild))
|
353
353
|
for step, _ in docBuild.iterBuildHTML(None):
|
354
354
|
self.docPreview.buildStep(step + 1)
|
355
|
-
|
355
|
+
QApplication.processEvents()
|
356
356
|
|
357
357
|
buildObj = docBuild.lastBuild
|
358
358
|
assert isinstance(buildObj, ToHtml)
|
@@ -382,10 +382,9 @@ class GuiManuscript(QDialog):
|
|
382
382
|
@pyqtSlot()
|
383
383
|
def _buildManuscript(self) -> None:
|
384
384
|
"""Open the build dialog and build the manuscript."""
|
385
|
-
build
|
386
|
-
if isinstance(build, BuildSettings):
|
385
|
+
if build := self._getSelectedBuild():
|
387
386
|
dlgBuild = GuiManuscriptBuild(self, build)
|
388
|
-
dlgBuild.
|
387
|
+
dlgBuild.exec()
|
389
388
|
|
390
389
|
# After the build is done, save build settings changes
|
391
390
|
if build.changed:
|
@@ -398,7 +397,7 @@ class GuiManuscript(QDialog):
|
|
398
397
|
"""Open the print preview dialog."""
|
399
398
|
preview = QPrintPreviewDialog(self)
|
400
399
|
preview.paintRequested.connect(self.docPreview.printPreview)
|
401
|
-
preview.
|
400
|
+
preview.exec()
|
402
401
|
return
|
403
402
|
|
404
403
|
##
|
@@ -473,20 +472,16 @@ class GuiManuscript(QDialog):
|
|
473
472
|
|
474
473
|
def _openSettingsDialog(self, build: BuildSettings) -> None:
|
475
474
|
"""Open the build settings dialog."""
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
logger.debug("Found instance of GuiBuildSettings")
|
481
|
-
obj.show()
|
482
|
-
obj.raise_()
|
483
|
-
return
|
475
|
+
if dialog := self._findSettingsDialog(build.buildID):
|
476
|
+
dialog.show()
|
477
|
+
dialog.raise_()
|
478
|
+
return
|
484
479
|
|
485
480
|
dlgSettings = GuiBuildSettings(self.mainGui, build)
|
486
481
|
dlgSettings.setModal(False)
|
487
482
|
dlgSettings.show()
|
488
483
|
dlgSettings.raise_()
|
489
|
-
|
484
|
+
QApplication.processEvents()
|
490
485
|
dlgSettings.loadContent()
|
491
486
|
dlgSettings.newSettingsReady.connect(self._processNewSettings)
|
492
487
|
|
@@ -495,6 +490,7 @@ class GuiManuscript(QDialog):
|
|
495
490
|
def _updateBuildsList(self) -> None:
|
496
491
|
"""Update the list of available builds."""
|
497
492
|
self.buildList.clear()
|
493
|
+
self._buildMap.clear()
|
498
494
|
for key, name in self._builds.builds():
|
499
495
|
bItem = QListWidgetItem()
|
500
496
|
bItem.setText(name)
|
@@ -513,6 +509,15 @@ class GuiManuscript(QDialog):
|
|
513
509
|
self._updateBuildsList()
|
514
510
|
return
|
515
511
|
|
512
|
+
def _findSettingsDialog(self, buildID: str) -> GuiBuildSettings | None:
|
513
|
+
"""Return an open build settings dialog for a given build, if
|
514
|
+
one exists.
|
515
|
+
"""
|
516
|
+
for obj in SHARED.mainGui.children():
|
517
|
+
if isinstance(obj, GuiBuildSettings) and obj.buildID == buildID:
|
518
|
+
return obj
|
519
|
+
return None
|
520
|
+
|
516
521
|
# END Class GuiManuscript
|
517
522
|
|
518
523
|
|
@@ -526,7 +531,7 @@ class _DetailsWidget(QWidget):
|
|
526
531
|
# Tree Widget
|
527
532
|
self.listView = QTreeWidget(self)
|
528
533
|
self.listView.setHeaderLabels([self.tr("Setting"), self.tr("Value")])
|
529
|
-
self.listView.setIndentation(SHARED.theme.
|
534
|
+
self.listView.setIndentation(SHARED.theme.baseIconHeight)
|
530
535
|
self.listView.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
|
531
536
|
|
532
537
|
# Assemble
|
@@ -626,7 +631,7 @@ class _DetailsWidget(QWidget):
|
|
626
631
|
("headings.fmtChapter", "headings.hideChapter"),
|
627
632
|
("headings.fmtUnnumbered", "headings.hideUnnumbered"),
|
628
633
|
("headings.fmtScene", "headings.hideScene"),
|
629
|
-
("headings.
|
634
|
+
("headings.fmtAltScene", "headings.hideAltScene"),
|
630
635
|
("headings.fmtSection", "headings.hideSection"),
|
631
636
|
]:
|
632
637
|
sub = QTreeWidgetItem()
|
@@ -661,7 +666,7 @@ class _DetailsWidget(QWidget):
|
|
661
666
|
|
662
667
|
class _OutlineWidget(QWidget):
|
663
668
|
|
664
|
-
D_LINE =
|
669
|
+
D_LINE = QtUserRole
|
665
670
|
|
666
671
|
outlineEntryClicked = pyqtSignal(str)
|
667
672
|
|
@@ -721,7 +726,9 @@ class _OutlineWidget(QWidget):
|
|
721
726
|
parent.addChild(item)
|
722
727
|
indent = True
|
723
728
|
|
724
|
-
self.listView.setIndentation(
|
729
|
+
self.listView.setIndentation(
|
730
|
+
SHARED.theme.baseIconHeight if indent else CONFIG.pxInt(4)
|
731
|
+
)
|
725
732
|
self._outline = data
|
726
733
|
|
727
734
|
return
|
@@ -745,11 +752,12 @@ class _PreviewWidget(QTextBrowser):
|
|
745
752
|
|
746
753
|
self._docTime = 0
|
747
754
|
self._buildName = ""
|
755
|
+
self._scrollPos = 0
|
748
756
|
|
749
757
|
# Document Setup
|
750
758
|
dPalette = self.palette()
|
751
|
-
dPalette.setColor(QPalette.Base, QColor(255, 255, 255))
|
752
|
-
dPalette.setColor(QPalette.Text, QColor(0, 0, 0))
|
759
|
+
dPalette.setColor(QPalette.ColorRole.Base, QColor(255, 255, 255))
|
760
|
+
dPalette.setColor(QPalette.ColorRole.Text, QColor(0, 0, 0))
|
753
761
|
self.setPalette(dPalette)
|
754
762
|
|
755
763
|
self.setMinimumWidth(40*SHARED.theme.textNWidth)
|
@@ -766,8 +774,8 @@ class _PreviewWidget(QTextBrowser):
|
|
766
774
|
|
767
775
|
# Document Age
|
768
776
|
aPalette = self.palette()
|
769
|
-
aPalette.setColor(QPalette.
|
770
|
-
aPalette.setColor(QPalette.
|
777
|
+
aPalette.setColor(QPalette.ColorRole.Window, aPalette.toolTipBase().color())
|
778
|
+
aPalette.setColor(QPalette.ColorRole.WindowText, aPalette.toolTipText().color())
|
771
779
|
|
772
780
|
aFont = self.font()
|
773
781
|
aFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
@@ -777,7 +785,7 @@ class _PreviewWidget(QTextBrowser):
|
|
777
785
|
self.ageLabel.setFont(aFont)
|
778
786
|
self.ageLabel.setPalette(aPalette)
|
779
787
|
self.ageLabel.setAutoFillBackground(True)
|
780
|
-
self.ageLabel.setAlignment(
|
788
|
+
self.ageLabel.setAlignment(QtAlignCenter)
|
781
789
|
self.ageLabel.setFixedHeight(int(2.1*SHARED.theme.fontPixelSize))
|
782
790
|
|
783
791
|
# Progress
|
@@ -816,9 +824,9 @@ class _PreviewWidget(QTextBrowser):
|
|
816
824
|
"""Enable/disable the justify text option."""
|
817
825
|
pOptions = self.document().defaultTextOption()
|
818
826
|
if state:
|
819
|
-
pOptions.setAlignment(
|
827
|
+
pOptions.setAlignment(QtAlignJustify)
|
820
828
|
else:
|
821
|
-
pOptions.setAlignment(
|
829
|
+
pOptions.setAlignment(QtAlignAbsolute)
|
822
830
|
self.document().setDefaultTextOption(pOptions)
|
823
831
|
return
|
824
832
|
|
@@ -841,6 +849,7 @@ class _PreviewWidget(QTextBrowser):
|
|
841
849
|
self.buildProgress.setValue(0)
|
842
850
|
self.buildProgress.setCentreText(None)
|
843
851
|
self.buildProgress.setVisible(True)
|
852
|
+
self._scrollPos = self.verticalScrollBar().value()
|
844
853
|
self.setPlaceholderText("")
|
845
854
|
self.clear()
|
846
855
|
return
|
@@ -848,16 +857,15 @@ class _PreviewWidget(QTextBrowser):
|
|
848
857
|
def buildStep(self, value: int) -> None:
|
849
858
|
"""Update the progress bar value."""
|
850
859
|
self.buildProgress.setValue(value)
|
851
|
-
|
860
|
+
QApplication.processEvents()
|
852
861
|
return
|
853
862
|
|
854
863
|
def setContent(self, data: dict) -> None:
|
855
864
|
"""Set the content of the preview widget."""
|
856
|
-
|
857
|
-
qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
865
|
+
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
858
866
|
|
859
867
|
self.buildProgress.setCentreText(self.tr("Processing ..."))
|
860
|
-
|
868
|
+
QApplication.processEvents()
|
861
869
|
|
862
870
|
styles = "\n".join(data.get("styles", []))
|
863
871
|
self.document().setDefaultStyleSheet(styles)
|
@@ -865,12 +873,11 @@ class _PreviewWidget(QTextBrowser):
|
|
865
873
|
html = "".join(data.get("html", []))
|
866
874
|
html = html.replace("\t", "!!tab!!")
|
867
875
|
self.setHtml(html)
|
868
|
-
|
876
|
+
QApplication.processEvents()
|
869
877
|
while self.find("!!tab!!"):
|
870
878
|
cursor = self.textCursor()
|
871
879
|
cursor.insertText("\t")
|
872
880
|
|
873
|
-
self.verticalScrollBar().setValue(sPos)
|
874
881
|
self._docTime = checkInt(data.get("time"), 0)
|
875
882
|
self._updateBuildAge()
|
876
883
|
|
@@ -879,9 +886,9 @@ class _PreviewWidget(QTextBrowser):
|
|
879
886
|
self.document().markContentsDirty(0, self.document().characterCount())
|
880
887
|
|
881
888
|
self.buildProgress.setCentreText(self.tr("Done"))
|
882
|
-
|
883
|
-
|
884
|
-
QTimer.singleShot(300, self.
|
889
|
+
QApplication.restoreOverrideCursor()
|
890
|
+
QApplication.processEvents()
|
891
|
+
QTimer.singleShot(300, self._postUpdate)
|
885
892
|
|
886
893
|
return
|
887
894
|
|
@@ -902,10 +909,10 @@ class _PreviewWidget(QTextBrowser):
|
|
902
909
|
@pyqtSlot("QPrinter*")
|
903
910
|
def printPreview(self, printer: QPrinter) -> None:
|
904
911
|
"""Connect the print preview painter to the document viewer."""
|
905
|
-
|
906
|
-
printer.setOrientation(QPrinter.Portrait)
|
912
|
+
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
913
|
+
printer.setOrientation(QPrinter.Orientation.Portrait)
|
907
914
|
self.document().print(printer)
|
908
|
-
|
915
|
+
QApplication.restoreOverrideCursor()
|
909
916
|
return
|
910
917
|
|
911
918
|
@pyqtSlot(str)
|
@@ -936,9 +943,10 @@ class _PreviewWidget(QTextBrowser):
|
|
936
943
|
return
|
937
944
|
|
938
945
|
@pyqtSlot()
|
939
|
-
def
|
940
|
-
"""
|
946
|
+
def _postUpdate(self) -> None:
|
947
|
+
"""Run tasks after content update."""
|
941
948
|
self.buildProgress.setVisible(False)
|
949
|
+
self.verticalScrollBar().setValue(self._scrollPos)
|
942
950
|
return
|
943
951
|
|
944
952
|
##
|
@@ -976,13 +984,7 @@ class _StatsWidget(QWidget):
|
|
976
984
|
self.minWidget = QWidget(self)
|
977
985
|
self.maxWidget = QWidget(self)
|
978
986
|
|
979
|
-
|
980
|
-
toggleIcon = SHARED.theme.getToggleIcon("unfold", (iPx, iPx))
|
981
|
-
|
982
|
-
self.toggleButton = NIconToolButton(self, iPx)
|
983
|
-
self.toggleButton.setCheckable(True)
|
984
|
-
self.toggleButton.setIcon(toggleIcon)
|
985
|
-
self.toggleButton.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON))
|
987
|
+
self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize, "unfold")
|
986
988
|
self.toggleButton.toggled.connect(self._toggleView)
|
987
989
|
|
988
990
|
self._buildMinimal()
|
@@ -993,8 +995,8 @@ class _StatsWidget(QWidget):
|
|
993
995
|
self.mainStack.addWidget(self.maxWidget)
|
994
996
|
|
995
997
|
self.outerBox = QHBoxLayout()
|
996
|
-
self.outerBox.addWidget(self.toggleButton, 0,
|
997
|
-
self.outerBox.addWidget(self.mainStack, 1,
|
998
|
+
self.outerBox.addWidget(self.toggleButton, 0, QtAlignTop)
|
999
|
+
self.outerBox.addWidget(self.mainStack, 1, QtAlignTop)
|
998
1000
|
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
999
1001
|
|
1000
1002
|
self.setLayout(self.outerBox)
|
@@ -1011,7 +1013,7 @@ class _StatsWidget(QWidget):
|
|
1011
1013
|
|
1012
1014
|
# Maximal
|
1013
1015
|
self.maxTotalWords.setText("{0:n}".format(data.get("allWords", 0)))
|
1014
|
-
self.
|
1016
|
+
self.maxHeadWords.setText("{0:n}".format(data.get("titleWords", 0)))
|
1015
1017
|
self.maxTextWords.setText("{0:n}".format(data.get("textWords", 0)))
|
1016
1018
|
self.maxTitleCount.setText("{0:n}".format(data.get("titleCount", 0)))
|
1017
1019
|
self.maxParCount.setText("{0:n}".format(data.get("paragraphCount", 0)))
|
@@ -1021,7 +1023,7 @@ class _StatsWidget(QWidget):
|
|
1021
1023
|
self.maxTextChars.setText("{0:n}".format(data.get("textChars", 0)))
|
1022
1024
|
|
1023
1025
|
self.maxTotalWordChars.setText("{0:n}".format(data.get("allWordChars", 0)))
|
1024
|
-
self.
|
1026
|
+
self.maxHeadWordChars.setText("{0:n}".format(data.get("titleWordChars", 0)))
|
1025
1027
|
self.maxTextWordChars.setText("{0:n}".format(data.get("textWordChars", 0)))
|
1026
1028
|
|
1027
1029
|
return
|
@@ -1057,10 +1059,10 @@ class _StatsWidget(QWidget):
|
|
1057
1059
|
"""Build the minimal stats page."""
|
1058
1060
|
mPx = CONFIG.pxInt(8)
|
1059
1061
|
|
1060
|
-
self.lblWordCount = QLabel(self.tr("Words"))
|
1062
|
+
self.lblWordCount = QLabel(self.tr("Words"), self)
|
1061
1063
|
self.minWordCount = QLabel(self)
|
1062
1064
|
|
1063
|
-
self.lblCharCount = QLabel(self.tr("Characters"))
|
1065
|
+
self.lblCharCount = QLabel(self.tr("Characters"), self)
|
1064
1066
|
self.minCharCount = QLabel(self)
|
1065
1067
|
|
1066
1068
|
# Assemble
|
@@ -1083,25 +1085,23 @@ class _StatsWidget(QWidget):
|
|
1083
1085
|
hPx = CONFIG.pxInt(12)
|
1084
1086
|
vPx = CONFIG.pxInt(4)
|
1085
1087
|
|
1086
|
-
alignRight = Qt.AlignmentFlag.AlignRight
|
1087
|
-
|
1088
1088
|
# Left Column
|
1089
1089
|
self.maxTotalWords = QLabel(self)
|
1090
|
-
self.
|
1090
|
+
self.maxHeadWords = QLabel(self)
|
1091
1091
|
self.maxTextWords = QLabel(self)
|
1092
1092
|
self.maxTitleCount = QLabel(self)
|
1093
1093
|
self.maxParCount = QLabel(self)
|
1094
1094
|
|
1095
|
-
self.maxTotalWords.setAlignment(
|
1096
|
-
self.
|
1097
|
-
self.maxTextWords.setAlignment(
|
1098
|
-
self.maxTitleCount.setAlignment(
|
1099
|
-
self.maxParCount.setAlignment(
|
1095
|
+
self.maxTotalWords.setAlignment(QtAlignRight)
|
1096
|
+
self.maxHeadWords.setAlignment(QtAlignRight)
|
1097
|
+
self.maxTextWords.setAlignment(QtAlignRight)
|
1098
|
+
self.maxTitleCount.setAlignment(QtAlignRight)
|
1099
|
+
self.maxParCount.setAlignment(QtAlignRight)
|
1100
1100
|
|
1101
1101
|
self.leftForm = QFormLayout()
|
1102
1102
|
self.leftForm.addRow(self.tr("Words"), self.maxTotalWords)
|
1103
|
-
self.leftForm.addRow(self.tr("
|
1104
|
-
self.leftForm.addRow(self.tr("
|
1103
|
+
self.leftForm.addRow(self.tr("Words in Headings"), self.maxHeadWords)
|
1104
|
+
self.leftForm.addRow(self.tr("Words in Text"), self.maxTextWords)
|
1105
1105
|
self.leftForm.addRow("", QLabel(self))
|
1106
1106
|
self.leftForm.addRow(self.tr("Headings"), self.maxTitleCount)
|
1107
1107
|
self.leftForm.addRow(self.tr("Paragraphs"), self.maxParCount)
|
@@ -1114,24 +1114,24 @@ class _StatsWidget(QWidget):
|
|
1114
1114
|
self.maxTextChars = QLabel(self)
|
1115
1115
|
|
1116
1116
|
self.maxTotalWordChars = QLabel(self)
|
1117
|
-
self.
|
1117
|
+
self.maxHeadWordChars = QLabel(self)
|
1118
1118
|
self.maxTextWordChars = QLabel(self)
|
1119
1119
|
|
1120
|
-
self.maxTotalChars.setAlignment(
|
1121
|
-
self.maxHeaderChars.setAlignment(
|
1122
|
-
self.maxTextChars.setAlignment(
|
1120
|
+
self.maxTotalChars.setAlignment(QtAlignRight)
|
1121
|
+
self.maxHeaderChars.setAlignment(QtAlignRight)
|
1122
|
+
self.maxTextChars.setAlignment(QtAlignRight)
|
1123
1123
|
|
1124
|
-
self.maxTotalWordChars.setAlignment(
|
1125
|
-
self.
|
1126
|
-
self.maxTextWordChars.setAlignment(
|
1124
|
+
self.maxTotalWordChars.setAlignment(QtAlignRight)
|
1125
|
+
self.maxHeadWordChars.setAlignment(QtAlignRight)
|
1126
|
+
self.maxTextWordChars.setAlignment(QtAlignRight)
|
1127
1127
|
|
1128
1128
|
self.rightForm = QFormLayout()
|
1129
1129
|
self.rightForm.addRow(self.tr("Characters"), self.maxTotalChars)
|
1130
|
-
self.rightForm.addRow(self.tr("
|
1131
|
-
self.rightForm.addRow(self.tr("
|
1130
|
+
self.rightForm.addRow(self.tr("Characters in Headings"), self.maxHeaderChars)
|
1131
|
+
self.rightForm.addRow(self.tr("Characters in Text"), self.maxTextChars)
|
1132
1132
|
self.rightForm.addRow(self.tr("Characters, No Spaces"), self.maxTotalWordChars)
|
1133
|
-
self.rightForm.addRow(self.tr("
|
1134
|
-
self.rightForm.addRow(self.tr("
|
1133
|
+
self.rightForm.addRow(self.tr("Characters in Headings, No Spaces"), self.maxHeadWordChars)
|
1134
|
+
self.rightForm.addRow(self.tr("Characters in Text, No Spaces"), self.maxTextWordChars)
|
1135
1135
|
self.rightForm.setHorizontalSpacing(hPx)
|
1136
1136
|
self.rightForm.setVerticalSpacing(vPx)
|
1137
1137
|
|