novelWriter 2.3rc1__py3-none-any.whl → 2.4__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.3rc1.dist-info → novelWriter-2.4.dist-info}/METADATA +5 -6
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/RECORD +119 -109
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/WHEEL +1 -1
- novelWriter-2.4.dist-info/entry_points.txt +2 -0
- novelwriter/__init__.py +17 -10
- 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/i18n/project_nl_NL.json +11 -0
- novelwriter/assets/i18n/project_pt_BR.json +11 -0
- novelwriter/assets/icons/none.svg +4 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_times.svg +1 -1
- 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 +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_times.svg +1 -1
- 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/assets/syntax/cyberpunk_night.conf +26 -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/tango.conf +23 -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 +25 -23
- novelwriter/assets/themes/cyberpunk_night.conf +29 -0
- novelwriter/common.py +12 -4
- novelwriter/config.py +47 -16
- novelwriter/constants.py +5 -6
- novelwriter/core/buildsettings.py +64 -44
- novelwriter/core/coretools.py +97 -13
- novelwriter/core/docbuild.py +74 -7
- novelwriter/core/document.py +24 -3
- novelwriter/core/index.py +31 -112
- novelwriter/core/project.py +11 -15
- novelwriter/core/projectxml.py +3 -2
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +3 -3
- novelwriter/core/status.py +6 -5
- novelwriter/core/storage.py +16 -6
- novelwriter/core/tohtml.py +22 -25
- novelwriter/core/tokenizer.py +417 -237
- novelwriter/core/tomd.py +17 -8
- novelwriter/core/toodt.py +386 -351
- novelwriter/core/tree.py +8 -8
- novelwriter/dialogs/about.py +10 -12
- novelwriter/dialogs/docmerge.py +17 -14
- novelwriter/dialogs/docsplit.py +20 -19
- novelwriter/dialogs/editlabel.py +5 -4
- novelwriter/dialogs/preferences.py +32 -40
- novelwriter/dialogs/projectsettings.py +31 -28
- novelwriter/dialogs/quotes.py +10 -9
- novelwriter/dialogs/wordlist.py +18 -15
- novelwriter/enum.py +17 -14
- novelwriter/error.py +14 -12
- novelwriter/extensions/circularprogress.py +12 -8
- novelwriter/extensions/configlayout.py +23 -3
- novelwriter/extensions/modified.py +51 -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/extensions/versioninfo.py +1 -1
- novelwriter/gui/doceditor.py +433 -496
- novelwriter/gui/dochighlight.py +54 -33
- novelwriter/gui/docviewer.py +162 -175
- novelwriter/gui/docviewerpanel.py +20 -37
- novelwriter/gui/editordocument.py +15 -4
- novelwriter/gui/itemdetails.py +51 -54
- novelwriter/gui/mainmenu.py +37 -17
- novelwriter/gui/noveltree.py +31 -37
- novelwriter/gui/outline.py +120 -98
- novelwriter/gui/projtree.py +114 -112
- novelwriter/gui/search.py +362 -0
- novelwriter/gui/sidebar.py +36 -45
- novelwriter/gui/statusbar.py +14 -14
- novelwriter/gui/theme.py +116 -34
- novelwriter/guimain.py +216 -207
- novelwriter/shared.py +31 -6
- novelwriter/text/counting.py +138 -0
- novelwriter/tools/dictionaries.py +15 -14
- novelwriter/tools/lipsum.py +20 -17
- novelwriter/tools/manusbuild.py +43 -35
- novelwriter/tools/manuscript.py +381 -104
- novelwriter/tools/manussettings.py +263 -125
- novelwriter/tools/noveldetails.py +21 -19
- novelwriter/tools/welcome.py +59 -57
- novelwriter/tools/writingstats.py +61 -55
- novelwriter/types.py +90 -0
- novelWriter-2.3rc1.dist-info/entry_points.txt +0 -5
- 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/tools/__init__.py +0 -3
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/top_level.txt +0 -0
novelwriter/gui/docviewer.py
CHANGED
@@ -29,27 +29,29 @@ from __future__ import annotations
|
|
29
29
|
import logging
|
30
30
|
|
31
31
|
from enum import Enum
|
32
|
-
from typing import TYPE_CHECKING
|
33
32
|
|
34
|
-
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QPoint,
|
33
|
+
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QPoint, Qt, QUrl
|
35
34
|
from PyQt5.QtGui import (
|
36
35
|
QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor,
|
37
36
|
QTextOption
|
38
37
|
)
|
39
38
|
from PyQt5.QtWidgets import (
|
40
|
-
QAction, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
|
41
|
-
|
39
|
+
QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
|
40
|
+
QToolButton, QWidget
|
42
41
|
)
|
43
42
|
|
44
43
|
from novelwriter import CONFIG, SHARED
|
44
|
+
from novelwriter.common import cssCol
|
45
|
+
from novelwriter.constants import nwHeaders, nwUnicode
|
46
|
+
from novelwriter.core.tohtml import ToHtml
|
45
47
|
from novelwriter.enum import nwItemType, nwDocAction, nwDocMode
|
46
48
|
from novelwriter.error import logException
|
47
|
-
from novelwriter.constants import nwUnicode
|
48
|
-
from novelwriter.core.tohtml import ToHtml
|
49
49
|
from novelwriter.extensions.eventfilters import WheelEventFilter
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
from novelwriter.extensions.modified import NIconToolButton
|
51
|
+
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
52
|
+
from novelwriter.types import (
|
53
|
+
QtAlignCenterTop, QtAlignJustify, QtKeepAnchor, QtMouseLeft, QtMoveAnchor
|
54
|
+
)
|
53
55
|
|
54
56
|
logger = logging.getLogger(__name__)
|
55
57
|
|
@@ -58,17 +60,16 @@ class GuiDocViewer(QTextBrowser):
|
|
58
60
|
|
59
61
|
documentLoaded = pyqtSignal(str)
|
60
62
|
loadDocumentTagRequest = pyqtSignal(str, Enum)
|
63
|
+
closeDocumentRequest = pyqtSignal()
|
64
|
+
reloadDocumentRequest = pyqtSignal()
|
61
65
|
togglePanelVisibility = pyqtSignal()
|
62
66
|
requestProjectItemSelected = pyqtSignal(str, bool)
|
63
67
|
|
64
|
-
def __init__(self,
|
65
|
-
super().__init__(parent=
|
68
|
+
def __init__(self, parent: QWidget) -> None:
|
69
|
+
super().__init__(parent=parent)
|
66
70
|
|
67
71
|
logger.debug("Create: GuiDocViewer")
|
68
72
|
|
69
|
-
# Class Variables
|
70
|
-
self.mainGui = mainGui
|
71
|
-
|
72
73
|
# Internal Variables
|
73
74
|
self._docHandle = None
|
74
75
|
|
@@ -128,7 +129,7 @@ class GuiDocViewer(QTextBrowser):
|
|
128
129
|
self.clear()
|
129
130
|
self.setSearchPaths([""])
|
130
131
|
self._docHandle = None
|
131
|
-
self.docHeader.
|
132
|
+
self.docHeader.clearHeader()
|
132
133
|
return
|
133
134
|
|
134
135
|
def updateTheme(self) -> None:
|
@@ -166,7 +167,7 @@ class GuiDocViewer(QTextBrowser):
|
|
166
167
|
self.document().setDocumentMargin(0)
|
167
168
|
options = QTextOption()
|
168
169
|
if CONFIG.doJustify:
|
169
|
-
options.setAlignment(
|
170
|
+
options.setAlignment(QtAlignJustify)
|
170
171
|
self.document().setDefaultTextOption(options)
|
171
172
|
|
172
173
|
# Scroll bars
|
@@ -184,8 +185,7 @@ class GuiDocViewer(QTextBrowser):
|
|
184
185
|
self.setTabStopDistance(CONFIG.getTabWidth())
|
185
186
|
|
186
187
|
# If we have a document open, we should reload it in case the font changed
|
187
|
-
|
188
|
-
self.reloadText()
|
188
|
+
self.reloadText()
|
189
189
|
|
190
190
|
return
|
191
191
|
|
@@ -197,12 +197,15 @@ class GuiDocViewer(QTextBrowser):
|
|
197
197
|
return False
|
198
198
|
|
199
199
|
logger.debug("Generating preview for item '%s'", tHandle)
|
200
|
-
|
200
|
+
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
201
201
|
|
202
202
|
sPos = self.verticalScrollBar().value()
|
203
203
|
aDoc = ToHtml(SHARED.project)
|
204
|
-
aDoc.setPreview(
|
205
|
-
aDoc.
|
204
|
+
aDoc.setPreview(True)
|
205
|
+
aDoc.setKeywords(True)
|
206
|
+
aDoc.setComments(CONFIG.viewComments)
|
207
|
+
aDoc.setSynopsis(CONFIG.viewSynopsis)
|
208
|
+
aDoc.setLinkHeadings(True)
|
206
209
|
|
207
210
|
# Be extra careful here to prevent crashes when first opening a
|
208
211
|
# project as a crash here leaves no way of recovering.
|
@@ -216,7 +219,7 @@ class GuiDocViewer(QTextBrowser):
|
|
216
219
|
logger.error("Failed to generate preview for document with handle '%s'", tHandle)
|
217
220
|
logException()
|
218
221
|
self.setText(self.tr("An error occurred while generating the preview."))
|
219
|
-
|
222
|
+
QApplication.restoreOverrideCursor()
|
220
223
|
return False
|
221
224
|
|
222
225
|
# Refresh the tab stops
|
@@ -239,13 +242,17 @@ class GuiDocViewer(QTextBrowser):
|
|
239
242
|
|
240
243
|
self._docHandle = tHandle
|
241
244
|
SHARED.project.data.setLastHandle(tHandle, "viewer")
|
242
|
-
self.docHeader.
|
245
|
+
self.docHeader.setHandle(tHandle)
|
246
|
+
self.docHeader.setOutline({
|
247
|
+
sTitle: (hItem.title, nwHeaders.H_LEVEL.get(hItem.level, 0))
|
248
|
+
for sTitle, hItem in SHARED.project.index.iterItemHeadings(tHandle)
|
249
|
+
})
|
243
250
|
self.updateDocMargins()
|
244
251
|
|
245
252
|
# Since we change the content while it may still be rendering, we mark
|
246
253
|
# the document dirty again to make sure it's re-rendered properly.
|
247
254
|
self.redrawText()
|
248
|
-
|
255
|
+
QApplication.restoreOverrideCursor()
|
249
256
|
self.documentLoaded.emit(tHandle)
|
250
257
|
|
251
258
|
return True
|
@@ -281,13 +288,6 @@ class GuiDocViewer(QTextBrowser):
|
|
281
288
|
return False
|
282
289
|
return True
|
283
290
|
|
284
|
-
def navigateTo(self, tAnchor: str) -> None:
|
285
|
-
"""Go to a specific #link in the document."""
|
286
|
-
if isinstance(tAnchor, str) and tAnchor.startswith("#"):
|
287
|
-
logger.debug("Moving to anchor '%s'", tAnchor)
|
288
|
-
self.setSource(QUrl(tAnchor))
|
289
|
-
return
|
290
|
-
|
291
291
|
def clearNavHistory(self) -> None:
|
292
292
|
"""Clear the navigation history."""
|
293
293
|
self.docHistory.clear()
|
@@ -340,11 +340,19 @@ class GuiDocViewer(QTextBrowser):
|
|
340
340
|
@pyqtSlot(str)
|
341
341
|
def updateDocInfo(self, tHandle: str) -> None:
|
342
342
|
"""Update the header title bar if needed."""
|
343
|
-
if tHandle == self._docHandle:
|
344
|
-
self.docHeader.
|
343
|
+
if tHandle and tHandle == self._docHandle:
|
344
|
+
self.docHeader.setHandle(tHandle)
|
345
345
|
self.updateDocMargins()
|
346
346
|
return
|
347
347
|
|
348
|
+
@pyqtSlot(str)
|
349
|
+
def navigateTo(self, anchor: str) -> None:
|
350
|
+
"""Go to a specific #link in the document."""
|
351
|
+
if isinstance(anchor, str) and anchor.startswith("#"):
|
352
|
+
logger.debug("Moving to anchor '%s'", anchor)
|
353
|
+
self.setSource(QUrl(anchor))
|
354
|
+
return
|
355
|
+
|
348
356
|
##
|
349
357
|
# Private Slots
|
350
358
|
##
|
@@ -404,7 +412,7 @@ class GuiDocViewer(QTextBrowser):
|
|
404
412
|
ctxMenu.addAction(mnuSelPara)
|
405
413
|
|
406
414
|
# Open the context menu
|
407
|
-
ctxMenu.
|
415
|
+
ctxMenu.exec(self.viewport().mapToGlobal(point))
|
408
416
|
ctxMenu.deleteLater()
|
409
417
|
|
410
418
|
return
|
@@ -446,8 +454,8 @@ class GuiDocViewer(QTextBrowser):
|
|
446
454
|
posE = cursor.selectionEnd()
|
447
455
|
selTxt = cursor.selectedText()
|
448
456
|
if selTxt.startswith(nwUnicode.U_PSEP):
|
449
|
-
cursor.setPosition(posS+1,
|
450
|
-
cursor.setPosition(posE,
|
457
|
+
cursor.setPosition(posS+1, QtMoveAnchor)
|
458
|
+
cursor.setPosition(posE, QtKeepAnchor)
|
451
459
|
|
452
460
|
self.setTextCursor(cursor)
|
453
461
|
|
@@ -463,53 +471,25 @@ class GuiDocViewer(QTextBrowser):
|
|
463
471
|
"""Generate an appropriate style sheet for the document viewer,
|
464
472
|
based on the current syntax highlighter theme.
|
465
473
|
"""
|
466
|
-
colText = SHARED.theme.colText
|
467
|
-
colHead = SHARED.theme.colHead
|
468
|
-
colVals = SHARED.theme.colVal
|
469
|
-
|
470
|
-
colKeys = SHARED.theme.colKey
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
"body {{"
|
476
|
-
"
|
477
|
-
"}}\n"
|
478
|
-
"
|
479
|
-
"
|
480
|
-
"}}\n"
|
481
|
-
"
|
482
|
-
"
|
483
|
-
"}
|
484
|
-
"mark {{"
|
485
|
-
" color: rgb({eColR}, {eColG}, {eColB});"
|
486
|
-
"}}\n"
|
487
|
-
".tags {{"
|
488
|
-
" color: rgb({kColR}, {kColG}, {kColB});"
|
489
|
-
"}}\n"
|
490
|
-
".optional {{"
|
491
|
-
" color: rgb({oColR}, {oColG}, {oColB});"
|
492
|
-
"}}\n"
|
493
|
-
".comment {{"
|
494
|
-
" color: rgb({cColR}, {cColG}, {cColB});"
|
495
|
-
"}}\n"
|
496
|
-
".synopsis {{"
|
497
|
-
" color: rgb({mColR}, {mColG}, {mColB});"
|
498
|
-
"}}\n"
|
499
|
-
".title {{"
|
500
|
-
" text-align: center;"
|
501
|
-
"}}\n"
|
502
|
-
).format(
|
503
|
-
tColR=colText.red(), tColG=colText.green(), tColB=colText.blue(),
|
504
|
-
hColR=colHead.red(), hColG=colHead.green(), hColB=colHead.blue(),
|
505
|
-
aColR=colVals.red(), aColG=colVals.green(), aColB=colVals.blue(),
|
506
|
-
eColR=colEmph.red(), eColG=colEmph.green(), eColB=colEmph.blue(),
|
507
|
-
kColR=colKeys.red(), kColG=colKeys.green(), kColB=colKeys.blue(),
|
508
|
-
cColR=colHide.red(), cColG=colHide.green(), cColB=colHide.blue(),
|
509
|
-
mColR=colMods.red(), mColG=colMods.green(), mColB=colMods.blue(),
|
510
|
-
oColR=colOpts.red(), oColG=colOpts.green(), oColB=colOpts.blue(),
|
474
|
+
colText = cssCol(SHARED.theme.colText)
|
475
|
+
colHead = cssCol(SHARED.theme.colHead)
|
476
|
+
colVals = cssCol(SHARED.theme.colVal)
|
477
|
+
colMark = cssCol(SHARED.theme.colMark)
|
478
|
+
colKeys = cssCol(SHARED.theme.colKey)
|
479
|
+
colOpts = cssCol(SHARED.theme.colOpt)
|
480
|
+
colHide = cssCol(SHARED.theme.colHidden)
|
481
|
+
colMods = cssCol(SHARED.theme.colMod)
|
482
|
+
self.document().setDefaultStyleSheet(
|
483
|
+
f"body {{color: {colText};}}\n"
|
484
|
+
f"h1, h2, h3, h4 {{color: {colHead};}}\n"
|
485
|
+
f"a {{color: {colVals};}}\n"
|
486
|
+
f"mark {{background-color: {colMark};}}\n"
|
487
|
+
f".tags {{color: {colKeys};}}\n"
|
488
|
+
f".optional {{color: {colOpts};}}\n"
|
489
|
+
f".comment {{color: {colHide};}}\n"
|
490
|
+
f".synopsis {{color: {colMods};}}\n"
|
491
|
+
".title {text-align: center;}\n"
|
511
492
|
)
|
512
|
-
self.document().setDefaultStyleSheet(styleSheet)
|
513
493
|
|
514
494
|
return
|
515
495
|
|
@@ -644,84 +624,81 @@ class GuiDocViewHeader(QWidget):
|
|
644
624
|
logger.debug("Create: GuiDocViewHeader")
|
645
625
|
|
646
626
|
self.docViewer = docViewer
|
647
|
-
self.mainGui = docViewer.mainGui
|
648
627
|
|
649
628
|
# Internal Variables
|
650
629
|
self._docHandle = None
|
630
|
+
self._docOutline: dict[str, tuple[str, int]] = {}
|
651
631
|
|
652
|
-
|
653
|
-
|
632
|
+
iPx = SHARED.theme.baseIconHeight
|
633
|
+
iSz = SHARED.theme.baseIconSize
|
634
|
+
mPx = CONFIG.pxInt(4)
|
654
635
|
|
655
636
|
# Main Widget Settings
|
656
637
|
self.setAutoFillBackground(True)
|
657
638
|
|
658
639
|
# Title Label
|
659
|
-
self.
|
660
|
-
self.
|
661
|
-
self.
|
662
|
-
self.
|
663
|
-
self.
|
664
|
-
self.
|
665
|
-
self.
|
666
|
-
self.
|
667
|
-
|
668
|
-
lblFont = self.
|
640
|
+
self.itemTitle = QLabel(self)
|
641
|
+
self.itemTitle.setText("")
|
642
|
+
self.itemTitle.setIndent(0)
|
643
|
+
self.itemTitle.setMargin(0)
|
644
|
+
self.itemTitle.setContentsMargins(0, 0, 0, 0)
|
645
|
+
self.itemTitle.setAutoFillBackground(True)
|
646
|
+
self.itemTitle.setAlignment(QtAlignCenterTop)
|
647
|
+
self.itemTitle.setFixedHeight(iPx)
|
648
|
+
|
649
|
+
lblFont = self.itemTitle.font()
|
669
650
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
670
|
-
self.
|
651
|
+
self.itemTitle.setFont(lblFont)
|
652
|
+
|
653
|
+
# Other Widgets
|
654
|
+
self.outlineMenu = QMenu(self)
|
671
655
|
|
672
656
|
# Buttons
|
673
|
-
self.
|
674
|
-
self.
|
675
|
-
self.
|
676
|
-
self.
|
677
|
-
|
657
|
+
self.outlineButton = NIconToolButton(self, iSz)
|
658
|
+
self.outlineButton.setVisible(False)
|
659
|
+
self.outlineButton.setToolTip(self.tr("Outline"))
|
660
|
+
self.outlineButton.setMenu(self.outlineMenu)
|
661
|
+
|
662
|
+
self.backButton = NIconToolButton(self, iSz)
|
678
663
|
self.backButton.setVisible(False)
|
679
664
|
self.backButton.setToolTip(self.tr("Go Backward"))
|
680
665
|
self.backButton.clicked.connect(self.docViewer.navBackward)
|
681
666
|
|
682
|
-
self.forwardButton =
|
683
|
-
self.forwardButton.setContentsMargins(0, 0, 0, 0)
|
684
|
-
self.forwardButton.setIconSize(QSize(fPx, fPx))
|
685
|
-
self.forwardButton.setFixedSize(fPx, fPx)
|
686
|
-
self.forwardButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
667
|
+
self.forwardButton = NIconToolButton(self, iSz)
|
687
668
|
self.forwardButton.setVisible(False)
|
688
669
|
self.forwardButton.setToolTip(self.tr("Go Forward"))
|
689
670
|
self.forwardButton.clicked.connect(self.docViewer.navForward)
|
690
671
|
|
691
|
-
self.refreshButton =
|
692
|
-
self.refreshButton.setContentsMargins(0, 0, 0, 0)
|
693
|
-
self.refreshButton.setIconSize(QSize(fPx, fPx))
|
694
|
-
self.refreshButton.setFixedSize(fPx, fPx)
|
695
|
-
self.refreshButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
672
|
+
self.refreshButton = NIconToolButton(self, iSz)
|
696
673
|
self.refreshButton.setVisible(False)
|
697
674
|
self.refreshButton.setToolTip(self.tr("Reload"))
|
698
675
|
self.refreshButton.clicked.connect(self._refreshDocument)
|
699
676
|
|
700
|
-
self.closeButton =
|
701
|
-
self.closeButton.setContentsMargins(0, 0, 0, 0)
|
702
|
-
self.closeButton.setIconSize(QSize(fPx, fPx))
|
703
|
-
self.closeButton.setFixedSize(fPx, fPx)
|
704
|
-
self.closeButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
677
|
+
self.closeButton = NIconToolButton(self, iSz)
|
705
678
|
self.closeButton.setVisible(False)
|
706
679
|
self.closeButton.setToolTip(self.tr("Close"))
|
707
680
|
self.closeButton.clicked.connect(self._closeDocument)
|
708
681
|
|
709
682
|
# Assemble Layout
|
710
683
|
self.outerBox = QHBoxLayout()
|
711
|
-
self.outerBox.
|
684
|
+
self.outerBox.addWidget(self.outlineButton, 0)
|
712
685
|
self.outerBox.addWidget(self.backButton, 0)
|
713
686
|
self.outerBox.addWidget(self.forwardButton, 0)
|
714
|
-
self.outerBox.
|
687
|
+
self.outerBox.addSpacing(mPx)
|
688
|
+
self.outerBox.addWidget(self.itemTitle, 1)
|
689
|
+
self.outerBox.addSpacing(mPx)
|
690
|
+
self.outerBox.addSpacing(iPx)
|
715
691
|
self.outerBox.addWidget(self.refreshButton, 0)
|
716
692
|
self.outerBox.addWidget(self.closeButton, 0)
|
693
|
+
self.outerBox.setSpacing(0)
|
694
|
+
|
717
695
|
self.setLayout(self.outerBox)
|
718
696
|
|
719
697
|
# Fix Margins and Size
|
720
698
|
# This is needed for high DPI systems. See issue #499.
|
721
|
-
cM = CONFIG.pxInt(8)
|
722
699
|
self.setContentsMargins(0, 0, 0, 0)
|
723
|
-
self.outerBox.setContentsMargins(
|
724
|
-
self.setMinimumHeight(
|
700
|
+
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
701
|
+
self.setMinimumHeight(iPx + 2*mPx)
|
725
702
|
|
726
703
|
# Fix the Colours
|
727
704
|
self.updateTheme()
|
@@ -734,19 +711,50 @@ class GuiDocViewHeader(QWidget):
|
|
734
711
|
# Methods
|
735
712
|
##
|
736
713
|
|
737
|
-
def
|
738
|
-
"""
|
739
|
-
self.
|
740
|
-
self.
|
741
|
-
self.refreshButton.setIcon(SHARED.theme.getIcon("refresh"))
|
742
|
-
self.closeButton.setIcon(SHARED.theme.getIcon("close"))
|
714
|
+
def clearHeader(self) -> None:
|
715
|
+
"""Clear the header."""
|
716
|
+
self._docHandle = None
|
717
|
+
self._docOutline = {}
|
743
718
|
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
719
|
+
self.itemTitle.setText("")
|
720
|
+
self.outlineMenu.clear()
|
721
|
+
self.outlineButton.setVisible(False)
|
722
|
+
self.backButton.setVisible(False)
|
723
|
+
self.forwardButton.setVisible(False)
|
724
|
+
self.closeButton.setVisible(False)
|
725
|
+
self.refreshButton.setVisible(False)
|
726
|
+
return
|
749
727
|
|
728
|
+
def setOutline(self, data: dict[str, tuple[str, int]]) -> None:
|
729
|
+
"""Set the document outline dataset."""
|
730
|
+
tHandle = self._docHandle
|
731
|
+
if data != self._docOutline and tHandle:
|
732
|
+
self.outlineMenu.clear()
|
733
|
+
entries = []
|
734
|
+
minLevel = 5
|
735
|
+
for title, (text, level) in data.items():
|
736
|
+
if title != "T0000":
|
737
|
+
entries.append((title, text, level))
|
738
|
+
minLevel = min(minLevel, level)
|
739
|
+
for title, text, level in entries[:30]:
|
740
|
+
indent = " "*(level - minLevel)
|
741
|
+
action = self.outlineMenu.addAction(f"{indent}{text}")
|
742
|
+
action.triggered.connect(
|
743
|
+
lambda _, title=title: self.docViewer.navigateTo(f"#{tHandle}:{title}")
|
744
|
+
)
|
745
|
+
self._docOutline = data
|
746
|
+
return
|
747
|
+
|
748
|
+
def updateTheme(self) -> None:
|
749
|
+
"""Update theme elements."""
|
750
|
+
self.outlineButton.setThemeIcon("list")
|
751
|
+
self.backButton.setThemeIcon("backward")
|
752
|
+
self.forwardButton.setThemeIcon("forward")
|
753
|
+
self.refreshButton.setThemeIcon("refresh")
|
754
|
+
self.closeButton.setThemeIcon("close")
|
755
|
+
|
756
|
+
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
|
757
|
+
self.outlineButton.setStyleSheet(buttonStyle)
|
750
758
|
self.backButton.setStyleSheet(buttonStyle)
|
751
759
|
self.forwardButton.setStyleSheet(buttonStyle)
|
752
760
|
self.refreshButton.setStyleSheet(buttonStyle)
|
@@ -765,38 +773,25 @@ class GuiDocViewHeader(QWidget):
|
|
765
773
|
palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
|
766
774
|
palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
|
767
775
|
self.setPalette(palette)
|
768
|
-
self.
|
776
|
+
self.itemTitle.setPalette(palette)
|
769
777
|
return
|
770
778
|
|
771
|
-
def
|
779
|
+
def setHandle(self, tHandle: str) -> None:
|
772
780
|
"""Sets the document title from the handle, or alternatively,
|
773
781
|
set the whole document path.
|
774
782
|
"""
|
775
783
|
self._docHandle = tHandle
|
776
|
-
|
777
|
-
self.docTitle.setText("")
|
778
|
-
self.backButton.setVisible(False)
|
779
|
-
self.forwardButton.setVisible(False)
|
780
|
-
self.closeButton.setVisible(False)
|
781
|
-
self.refreshButton.setVisible(False)
|
782
|
-
return
|
783
|
-
|
784
|
-
pTree = SHARED.project.tree
|
784
|
+
|
785
785
|
if CONFIG.showFullPath:
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
nwItem = pTree[aHandle]
|
790
|
-
if nwItem is not None:
|
791
|
-
tTitle.append(nwItem.itemName)
|
792
|
-
sSep = " %s " % nwUnicode.U_RSAQUO
|
793
|
-
self.docTitle.setText(sSep.join(tTitle))
|
786
|
+
self.itemTitle.setText(f" {nwUnicode.U_RSAQUO} ".join(reversed(
|
787
|
+
[name for name in SHARED.project.tree.getItemPath(tHandle, asName=True)]
|
788
|
+
)))
|
794
789
|
else:
|
795
|
-
if
|
796
|
-
self.docTitle.setText(nwItem.itemName)
|
790
|
+
self.itemTitle.setText(i.itemName if (i := SHARED.project.tree[tHandle]) else "")
|
797
791
|
|
798
792
|
self.backButton.setVisible(True)
|
799
793
|
self.forwardButton.setVisible(True)
|
794
|
+
self.outlineButton.setVisible(True)
|
800
795
|
self.closeButton.setVisible(True)
|
801
796
|
self.refreshButton.setVisible(True)
|
802
797
|
|
@@ -815,15 +810,14 @@ class GuiDocViewHeader(QWidget):
|
|
815
810
|
@pyqtSlot()
|
816
811
|
def _closeDocument(self) -> None:
|
817
812
|
"""Trigger the close editor/viewer on the main window."""
|
818
|
-
self.
|
813
|
+
self.clearHeader()
|
814
|
+
self.docViewer.closeDocumentRequest.emit()
|
819
815
|
return
|
820
816
|
|
821
817
|
@pyqtSlot()
|
822
818
|
def _refreshDocument(self) -> None:
|
823
819
|
"""Reload the content of the document."""
|
824
|
-
|
825
|
-
self.mainGui.saveDocument()
|
826
|
-
self.docViewer.reloadText()
|
820
|
+
self.docViewer.reloadDocumentRequest.emit()
|
827
821
|
return
|
828
822
|
|
829
823
|
##
|
@@ -834,7 +828,7 @@ class GuiDocViewHeader(QWidget):
|
|
834
828
|
"""Capture a click on the title and ensure that the item is
|
835
829
|
selected in the project tree.
|
836
830
|
"""
|
837
|
-
if event.button() ==
|
831
|
+
if event.button() == QtMouseLeft:
|
838
832
|
self.docViewer.requestProjectItemSelected.emit(self._docHandle, True)
|
839
833
|
return
|
840
834
|
|
@@ -854,22 +848,21 @@ class GuiDocViewFooter(QWidget):
|
|
854
848
|
logger.debug("Create: GuiDocViewFooter")
|
855
849
|
|
856
850
|
self.docViewer = docViewer
|
857
|
-
self.mainGui = docViewer.mainGui
|
858
851
|
|
859
852
|
# Internal Variables
|
860
853
|
self._docHandle = None
|
861
854
|
|
862
|
-
|
855
|
+
iPx = SHARED.theme.baseIconHeight
|
856
|
+
iSz = SHARED.theme.baseIconSize
|
863
857
|
hSp = CONFIG.pxInt(4)
|
858
|
+
mPx = CONFIG.pxInt(4)
|
864
859
|
|
865
860
|
# Main Widget Settings
|
866
861
|
self.setContentsMargins(0, 0, 0, 0)
|
867
862
|
self.setAutoFillBackground(True)
|
868
863
|
|
869
864
|
# Show/Hide Details
|
870
|
-
self.showHide =
|
871
|
-
self.showHide.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
872
|
-
self.showHide.setIconSize(QSize(fPx, fPx))
|
865
|
+
self.showHide = NIconToolButton(self, iSz)
|
873
866
|
self.showHide.clicked.connect(lambda: self.docViewer.togglePanelVisibility.emit())
|
874
867
|
self.showHide.setToolTip(self.tr("Show/Hide Viewer Panel"))
|
875
868
|
|
@@ -879,7 +872,7 @@ class GuiDocViewFooter(QWidget):
|
|
879
872
|
self.showComments.setCheckable(True)
|
880
873
|
self.showComments.setChecked(CONFIG.viewComments)
|
881
874
|
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
882
|
-
self.showComments.setIconSize(
|
875
|
+
self.showComments.setIconSize(iSz)
|
883
876
|
self.showComments.toggled.connect(self._doToggleComments)
|
884
877
|
self.showComments.setToolTip(self.tr("Show Comments"))
|
885
878
|
|
@@ -889,7 +882,7 @@ class GuiDocViewFooter(QWidget):
|
|
889
882
|
self.showSynopsis.setCheckable(True)
|
890
883
|
self.showSynopsis.setChecked(CONFIG.viewSynopsis)
|
891
884
|
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
892
|
-
self.showSynopsis.setIconSize(
|
885
|
+
self.showSynopsis.setIconSize(iSz)
|
893
886
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
894
887
|
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
895
888
|
|
@@ -909,10 +902,9 @@ class GuiDocViewFooter(QWidget):
|
|
909
902
|
|
910
903
|
# Fix Margins and Size
|
911
904
|
# This is needed for high DPI systems. See issue #499.
|
912
|
-
cM = CONFIG.pxInt(8)
|
913
905
|
self.setContentsMargins(0, 0, 0, 0)
|
914
|
-
self.outerBox.setContentsMargins(
|
915
|
-
self.setMinimumHeight(
|
906
|
+
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
907
|
+
self.setMinimumHeight(iPx + 2*mPx)
|
916
908
|
|
917
909
|
# Fix the Colours
|
918
910
|
self.updateTheme()
|
@@ -931,16 +923,11 @@ class GuiDocViewFooter(QWidget):
|
|
931
923
|
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
932
924
|
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx))
|
933
925
|
|
934
|
-
self.showHide.
|
926
|
+
self.showHide.setThemeIcon("panel")
|
935
927
|
self.showComments.setIcon(bulletIcon)
|
936
928
|
self.showSynopsis.setIcon(bulletIcon)
|
937
929
|
|
938
|
-
|
939
|
-
buttonStyle = (
|
940
|
-
"QToolButton {{border: none; background: transparent;}} "
|
941
|
-
"QToolButton:hover {{border: none; background: rgba({0}, {1}, {2}, 0.2);}}"
|
942
|
-
).format(colText.red(), colText.green(), colText.blue())
|
943
|
-
|
930
|
+
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
|
944
931
|
self.showHide.setStyleSheet(buttonStyle)
|
945
932
|
self.showComments.setStyleSheet(buttonStyle)
|
946
933
|
self.showSynopsis.setStyleSheet(buttonStyle)
|