novelWriter 2.2b1__py3-none-any.whl → 2.2.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.2b1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +3 -3
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +128 -114
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +10 -5
- 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_GB.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/novelwriter.ico +0 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +11 -3
- novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_panel.svg +4 -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_eye.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +11 -3
- novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_panel.svg +4 -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_eye.svg +4 -0
- novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/release_notes.htm +50 -7
- novelwriter/common.py +35 -27
- novelwriter/config.py +13 -28
- novelwriter/constants.py +21 -4
- novelwriter/core/buildsettings.py +2 -2
- novelwriter/core/coretools.py +8 -2
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +102 -36
- novelwriter/core/item.py +2 -2
- novelwriter/core/options.py +6 -3
- novelwriter/core/project.py +5 -5
- novelwriter/core/projectdata.py +3 -3
- novelwriter/core/projectxml.py +1 -1
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +4 -3
- novelwriter/core/status.py +3 -3
- novelwriter/core/storage.py +1 -1
- novelwriter/core/tohtml.py +11 -5
- novelwriter/core/tokenizer.py +28 -21
- novelwriter/core/tomd.py +6 -2
- novelwriter/core/toodt.py +12 -5
- novelwriter/core/tree.py +2 -2
- novelwriter/dialogs/about.py +30 -31
- novelwriter/dialogs/docmerge.py +24 -15
- novelwriter/dialogs/docsplit.py +27 -16
- novelwriter/dialogs/editlabel.py +19 -7
- novelwriter/dialogs/preferences.py +116 -131
- novelwriter/dialogs/projdetails.py +29 -36
- novelwriter/dialogs/projload.py +32 -36
- novelwriter/dialogs/projsettings.py +20 -15
- novelwriter/dialogs/quotes.py +32 -25
- novelwriter/dialogs/updates.py +17 -16
- novelwriter/dialogs/wordlist.py +34 -21
- novelwriter/enum.py +19 -8
- novelwriter/error.py +1 -1
- novelwriter/extensions/circularprogress.py +1 -1
- novelwriter/extensions/configlayout.py +3 -15
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/novelselector.py +1 -1
- novelwriter/extensions/pageddialog.py +1 -1
- novelwriter/extensions/pagedsidebar.py +2 -5
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +1 -1
- novelwriter/extensions/switch.py +4 -4
- novelwriter/extensions/switchbox.py +1 -6
- novelwriter/gui/doceditor.py +349 -236
- novelwriter/gui/dochighlight.py +10 -11
- novelwriter/gui/docviewer.py +158 -360
- novelwriter/gui/docviewerpanel.py +502 -0
- novelwriter/gui/editordocument.py +4 -4
- novelwriter/gui/itemdetails.py +2 -2
- novelwriter/gui/mainmenu.py +50 -36
- novelwriter/gui/noveltree.py +44 -53
- novelwriter/gui/outline.py +12 -7
- novelwriter/gui/projtree.py +465 -381
- novelwriter/gui/sidebar.py +9 -7
- novelwriter/gui/statusbar.py +48 -5
- novelwriter/gui/theme.py +26 -8
- novelwriter/guimain.py +212 -208
- novelwriter/shared.py +76 -30
- novelwriter/tools/dictionaries.py +268 -0
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +20 -10
- novelwriter/tools/manuscript.py +20 -27
- novelwriter/tools/manussettings.py +2 -4
- novelwriter/tools/projwizard.py +3 -3
- novelwriter/tools/writingstats.py +18 -5
- 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_dark/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
novelwriter/gui/docviewer.py
CHANGED
@@ -4,13 +4,12 @@ novelWriter – GUI Document Viewer
|
|
4
4
|
|
5
5
|
File History:
|
6
6
|
Created: 2019-05-10 [0.0.1] GuiDocViewer
|
7
|
-
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
|
8
7
|
Created: 2020-04-25 [0.4.5] GuiDocViewHeader
|
9
8
|
Created: 2020-06-09 [0.8] GuiDocViewFooter
|
10
9
|
Created: 2020-09-08 [1.0b1] GuiDocViewHistory
|
11
10
|
|
12
11
|
This file is a part of novelWriter
|
13
|
-
Copyright 2018–
|
12
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
14
13
|
|
15
14
|
This program is free software: you can redistribute it and/or modify
|
16
15
|
it under the terms of the GNU General Public License as published by
|
@@ -38,8 +37,8 @@ from PyQt5.QtGui import (
|
|
38
37
|
QTextOption
|
39
38
|
)
|
40
39
|
from PyQt5.QtWidgets import (
|
41
|
-
QAction,
|
42
|
-
|
40
|
+
QAction, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser, QToolButton,
|
41
|
+
QWidget, qApp
|
43
42
|
)
|
44
43
|
|
45
44
|
from novelwriter import CONFIG, SHARED
|
@@ -47,7 +46,7 @@ from novelwriter.enum import nwItemType, nwDocAction, nwDocMode
|
|
47
46
|
from novelwriter.error import logException
|
48
47
|
from novelwriter.constants import nwUnicode
|
49
48
|
from novelwriter.core.tohtml import ToHtml
|
50
|
-
from novelwriter.extensions.
|
49
|
+
from novelwriter.extensions.eventfilters import WheelEventFilter
|
51
50
|
|
52
51
|
if TYPE_CHECKING: # pragma: no cover
|
53
52
|
from novelwriter.guimain import GuiMain
|
@@ -57,7 +56,10 @@ logger = logging.getLogger(__name__)
|
|
57
56
|
|
58
57
|
class GuiDocViewer(QTextBrowser):
|
59
58
|
|
59
|
+
documentLoaded = pyqtSignal(str)
|
60
60
|
loadDocumentTagRequest = pyqtSignal(str, Enum)
|
61
|
+
togglePanelVisibility = pyqtSignal()
|
62
|
+
requestProjectItemSelected = pyqtSignal(str, bool)
|
61
63
|
|
62
64
|
def __init__(self, mainGui: GuiMain) -> None:
|
63
65
|
super().__init__(parent=mainGui)
|
@@ -74,8 +76,8 @@ class GuiDocViewer(QTextBrowser):
|
|
74
76
|
self.setMinimumWidth(CONFIG.pxInt(300))
|
75
77
|
self.setAutoFillBackground(True)
|
76
78
|
self.setOpenExternalLinks(False)
|
77
|
-
self.setFocusPolicy(Qt.StrongFocus)
|
78
|
-
self.setFrameStyle(QFrame.NoFrame)
|
79
|
+
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
80
|
+
self.setFrameStyle(QFrame.Shape.NoFrame)
|
79
81
|
|
80
82
|
# Document Header and Footer
|
81
83
|
self.docHeader = GuiDocViewHeader(self)
|
@@ -91,7 +93,7 @@ class GuiDocViewer(QTextBrowser):
|
|
91
93
|
self.installEventFilter(self.wheelEventFilter)
|
92
94
|
|
93
95
|
# Context Menu
|
94
|
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
96
|
+
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
95
97
|
self.customContextMenuRequested.connect(self._openContextMenu)
|
96
98
|
|
97
99
|
self.initViewer()
|
@@ -147,14 +149,14 @@ class GuiDocViewer(QTextBrowser):
|
|
147
149
|
|
148
150
|
# Set the widget colours to match syntax theme
|
149
151
|
mainPalette = self.palette()
|
150
|
-
mainPalette.setColor(QPalette.Window, QColor(*SHARED.theme.colBack))
|
151
|
-
mainPalette.setColor(QPalette.Base, QColor(*SHARED.theme.colBack))
|
152
|
-
mainPalette.setColor(QPalette.Text, QColor(*SHARED.theme.colText))
|
152
|
+
mainPalette.setColor(QPalette.ColorRole.Window, QColor(*SHARED.theme.colBack))
|
153
|
+
mainPalette.setColor(QPalette.ColorRole.Base, QColor(*SHARED.theme.colBack))
|
154
|
+
mainPalette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
153
155
|
self.setPalette(mainPalette)
|
154
156
|
|
155
157
|
docPalette = self.viewport().palette()
|
156
|
-
docPalette.setColor(QPalette.Base, QColor(*SHARED.theme.colBack))
|
157
|
-
docPalette.setColor(QPalette.Text, QColor(*SHARED.theme.colText))
|
158
|
+
docPalette.setColor(QPalette.ColorRole.Base, QColor(*SHARED.theme.colBack))
|
159
|
+
docPalette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
158
160
|
self.viewport().setPalette(docPalette)
|
159
161
|
|
160
162
|
self.docHeader.matchColours()
|
@@ -164,19 +166,19 @@ class GuiDocViewer(QTextBrowser):
|
|
164
166
|
self.document().setDocumentMargin(0)
|
165
167
|
theOpt = QTextOption()
|
166
168
|
if CONFIG.doJustify:
|
167
|
-
theOpt.setAlignment(Qt.AlignJustify)
|
169
|
+
theOpt.setAlignment(Qt.AlignmentFlag.AlignJustify)
|
168
170
|
self.document().setDefaultTextOption(theOpt)
|
169
171
|
|
170
172
|
# Scroll bars
|
171
173
|
if CONFIG.hideVScroll:
|
172
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
174
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
173
175
|
else:
|
174
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
176
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
175
177
|
|
176
178
|
if CONFIG.hideHScroll:
|
177
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
179
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
178
180
|
else:
|
179
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
181
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
180
182
|
|
181
183
|
# Refresh the tab stops
|
182
184
|
self.setTabStopDistance(CONFIG.getTabWidth())
|
@@ -191,10 +193,11 @@ class GuiDocViewer(QTextBrowser):
|
|
191
193
|
"""Load text into the viewer from an item handle."""
|
192
194
|
if not SHARED.project.tree.checkType(tHandle, nwItemType.FILE):
|
193
195
|
logger.warning("Item not found")
|
196
|
+
self.documentLoaded.emit("")
|
194
197
|
return False
|
195
198
|
|
196
199
|
logger.debug("Generating preview for item '%s'", tHandle)
|
197
|
-
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
|
200
|
+
qApp.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
198
201
|
|
199
202
|
sPos = self.verticalScrollBar().value()
|
200
203
|
aDoc = ToHtml(SHARED.project)
|
@@ -223,14 +226,12 @@ class GuiDocViewer(QTextBrowser):
|
|
223
226
|
if updateHistory:
|
224
227
|
self.docHistory.append(tHandle)
|
225
228
|
|
226
|
-
self.setHtml(aDoc.theResult.replace("\t", "!!tab!!"))
|
227
229
|
self.setDocumentTitle(tHandle)
|
228
230
|
|
229
|
-
#
|
230
|
-
|
231
|
+
# Replace tabs before setting the HTML, and then put them back in
|
232
|
+
self.setHtml(aDoc.theResult.replace("\t", "!!tab!!"))
|
231
233
|
while self.find("!!tab!!"):
|
232
|
-
|
233
|
-
theCursor.insertText("\t")
|
234
|
+
self.textCursor().insertText("\t")
|
234
235
|
|
235
236
|
if self._docHandle == tHandle:
|
236
237
|
# This is a refresh, so we set the scrollbar back to where it was
|
@@ -241,13 +242,11 @@ class GuiDocViewer(QTextBrowser):
|
|
241
242
|
self.docHeader.setTitleFromHandle(self._docHandle)
|
242
243
|
self.updateDocMargins()
|
243
244
|
|
244
|
-
# Make sure the main GUI knows we changed the content
|
245
|
-
self.mainGui.viewMeta.refreshReferences(tHandle)
|
246
|
-
|
247
245
|
# Since we change the content while it may still be rendering, we mark
|
248
246
|
# the document dirty again to make sure it's re-rendered properly.
|
249
247
|
self.redrawText()
|
250
248
|
qApp.restoreOverrideCursor()
|
249
|
+
self.documentLoaded.emit(tHandle)
|
251
250
|
|
252
251
|
return True
|
253
252
|
|
@@ -263,33 +262,31 @@ class GuiDocViewer(QTextBrowser):
|
|
263
262
|
self.updateDocMargins()
|
264
263
|
return
|
265
264
|
|
266
|
-
def docAction(self,
|
265
|
+
def docAction(self, action: nwDocAction) -> bool:
|
267
266
|
"""Process document actions on the current document."""
|
268
|
-
logger.debug("Requesting action: '%s'",
|
267
|
+
logger.debug("Requesting action: '%s'", action.name)
|
269
268
|
if self._docHandle is None:
|
270
269
|
logger.error("No document open")
|
271
270
|
return False
|
272
|
-
if
|
271
|
+
if action == nwDocAction.CUT:
|
273
272
|
self.copy()
|
274
|
-
elif
|
273
|
+
elif action == nwDocAction.COPY:
|
275
274
|
self.copy()
|
276
|
-
elif
|
277
|
-
self._makeSelection(QTextCursor.Document)
|
278
|
-
elif
|
279
|
-
self._makeSelection(QTextCursor.BlockUnderCursor)
|
275
|
+
elif action == nwDocAction.SEL_ALL:
|
276
|
+
self._makeSelection(QTextCursor.SelectionType.Document)
|
277
|
+
elif action == nwDocAction.SEL_PARA:
|
278
|
+
self._makeSelection(QTextCursor.SelectionType.BlockUnderCursor)
|
280
279
|
else:
|
281
|
-
logger.debug("Unknown or unsupported document action '%s'", str(
|
280
|
+
logger.debug("Unknown or unsupported document action '%s'", str(action))
|
282
281
|
return False
|
283
282
|
return True
|
284
283
|
|
285
|
-
def navigateTo(self, tAnchor: str) ->
|
284
|
+
def navigateTo(self, tAnchor: str) -> None:
|
286
285
|
"""Go to a specific #link in the document."""
|
287
|
-
if
|
288
|
-
return False
|
289
|
-
if tAnchor.startswith("#"):
|
286
|
+
if isinstance(tAnchor, str) and tAnchor.startswith("#"):
|
290
287
|
logger.debug("Moving to anchor '%s'", tAnchor)
|
291
288
|
self.setSource(QUrl(tAnchor))
|
292
|
-
return
|
289
|
+
return
|
293
290
|
|
294
291
|
def clearNavHistory(self) -> None:
|
295
292
|
"""Clear the navigation history."""
|
@@ -342,7 +339,7 @@ class GuiDocViewer(QTextBrowser):
|
|
342
339
|
|
343
340
|
@pyqtSlot(str)
|
344
341
|
def updateDocInfo(self, tHandle: str) -> None:
|
345
|
-
"""Update the header
|
342
|
+
"""Update the header title bar if needed."""
|
346
343
|
if tHandle == self._docHandle:
|
347
344
|
self.docHeader.setTitleFromHandle(self._docHandle)
|
348
345
|
self.updateDocMargins()
|
@@ -366,11 +363,11 @@ class GuiDocViewer(QTextBrowser):
|
|
366
363
|
|
367
364
|
@pyqtSlot("QUrl")
|
368
365
|
def _linkClicked(self, url: QUrl) -> None:
|
369
|
-
"""Process a clicked link
|
370
|
-
|
371
|
-
logger.debug("Clicked link: '%s'",
|
372
|
-
if len(
|
373
|
-
theBits =
|
366
|
+
"""Process a clicked link in the document."""
|
367
|
+
link = url.url()
|
368
|
+
logger.debug("Clicked link: '%s'", link)
|
369
|
+
if len(link) > 0:
|
370
|
+
theBits = link.split("=")
|
374
371
|
if len(theBits) == 2:
|
375
372
|
self.loadDocumentTagRequest.emit(theBits[1], nwDocMode.VIEW)
|
376
373
|
return
|
@@ -381,39 +378,34 @@ class GuiDocViewer(QTextBrowser):
|
|
381
378
|
userCursor = self.textCursor()
|
382
379
|
userSelection = userCursor.hasSelection()
|
383
380
|
|
384
|
-
|
385
|
-
|
386
|
-
# Cut, Copy and Paste
|
387
|
-
# ===================
|
381
|
+
ctxMenu = QMenu(self)
|
388
382
|
|
389
383
|
if userSelection:
|
390
|
-
mnuCopy = QAction(self.tr("Copy"),
|
384
|
+
mnuCopy = QAction(self.tr("Copy"), ctxMenu)
|
391
385
|
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
392
|
-
|
393
|
-
|
394
|
-
mnuContext.addSeparator()
|
386
|
+
ctxMenu.addAction(mnuCopy)
|
395
387
|
|
396
|
-
|
397
|
-
# ==========
|
388
|
+
ctxMenu.addSeparator()
|
398
389
|
|
399
|
-
mnuSelAll = QAction(self.tr("Select All"),
|
390
|
+
mnuSelAll = QAction(self.tr("Select All"), ctxMenu)
|
400
391
|
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
401
|
-
|
392
|
+
ctxMenu.addAction(mnuSelAll)
|
402
393
|
|
403
|
-
mnuSelWord = QAction(self.tr("Select Word"),
|
394
|
+
mnuSelWord = QAction(self.tr("Select Word"), ctxMenu)
|
404
395
|
mnuSelWord.triggered.connect(
|
405
|
-
lambda: self._makePosSelection(QTextCursor.WordUnderCursor, point)
|
396
|
+
lambda: self._makePosSelection(QTextCursor.SelectionType.WordUnderCursor, point)
|
406
397
|
)
|
407
|
-
|
398
|
+
ctxMenu.addAction(mnuSelWord)
|
408
399
|
|
409
|
-
mnuSelPara = QAction(self.tr("Select Paragraph"),
|
400
|
+
mnuSelPara = QAction(self.tr("Select Paragraph"), ctxMenu)
|
410
401
|
mnuSelPara.triggered.connect(
|
411
|
-
lambda: self._makePosSelection(QTextCursor.BlockUnderCursor, point)
|
402
|
+
lambda: self._makePosSelection(QTextCursor.SelectionType.BlockUnderCursor, point)
|
412
403
|
)
|
413
|
-
|
404
|
+
ctxMenu.addAction(mnuSelPara)
|
414
405
|
|
415
406
|
# Open the context menu
|
416
|
-
|
407
|
+
ctxMenu.exec_(self.viewport().mapToGlobal(point))
|
408
|
+
ctxMenu.deleteLater()
|
417
409
|
|
418
410
|
return
|
419
411
|
|
@@ -429,9 +421,9 @@ class GuiDocViewer(QTextBrowser):
|
|
429
421
|
|
430
422
|
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
|
431
423
|
"""Capture mouse click events on the document."""
|
432
|
-
if event.button() == Qt.BackButton:
|
424
|
+
if event.button() == Qt.MouseButton.BackButton:
|
433
425
|
self.navBackward()
|
434
|
-
elif event.button() == Qt.ForwardButton:
|
426
|
+
elif event.button() == Qt.MouseButton.ForwardButton:
|
435
427
|
self.navForward()
|
436
428
|
else:
|
437
429
|
super().mouseReleaseEvent(event)
|
@@ -442,29 +434,28 @@ class GuiDocViewer(QTextBrowser):
|
|
442
434
|
##
|
443
435
|
|
444
436
|
def _makeSelection(self, selType: QTextCursor.SelectionType) -> None:
|
445
|
-
"""Handle
|
446
|
-
|
447
|
-
|
448
|
-
|
437
|
+
"""Handle selection of text based on a selection mode."""
|
438
|
+
cursor = self.textCursor()
|
439
|
+
cursor.clearSelection()
|
440
|
+
cursor.select(selType)
|
449
441
|
|
450
|
-
if selType == QTextCursor.BlockUnderCursor:
|
442
|
+
if selType == QTextCursor.SelectionType.BlockUnderCursor:
|
451
443
|
# This selection mode also selects the preceding paragraph
|
452
444
|
# separator, which we want to avoid.
|
453
|
-
posS =
|
454
|
-
posE =
|
455
|
-
selTxt =
|
445
|
+
posS = cursor.selectionStart()
|
446
|
+
posE = cursor.selectionEnd()
|
447
|
+
selTxt = cursor.selectedText()
|
456
448
|
if selTxt.startswith(nwUnicode.U_PSEP):
|
457
|
-
|
458
|
-
|
449
|
+
cursor.setPosition(posS+1, QTextCursor.MoveMode.MoveAnchor)
|
450
|
+
cursor.setPosition(posE, QTextCursor.MoveMode.KeepAnchor)
|
459
451
|
|
460
|
-
self.setTextCursor(
|
452
|
+
self.setTextCursor(cursor)
|
461
453
|
|
462
454
|
return
|
463
455
|
|
464
456
|
def _makePosSelection(self, selType: QTextCursor.SelectionType, pos: QPoint) -> None:
|
465
457
|
"""Handle text selection at a given location."""
|
466
|
-
|
467
|
-
self.setTextCursor(theCursor)
|
458
|
+
self.setTextCursor(self.cursorForPosition(pos))
|
468
459
|
self._makeSelection(selType)
|
469
460
|
return
|
470
461
|
|
@@ -530,20 +521,16 @@ class GuiDocViewer(QTextBrowser):
|
|
530
521
|
|
531
522
|
class GuiDocViewHistory:
|
532
523
|
|
533
|
-
def __init__(self, docViewer):
|
534
|
-
|
524
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
535
525
|
self.docViewer = docViewer
|
536
|
-
|
537
526
|
self._navHistory = []
|
538
527
|
self._posHistory = []
|
539
528
|
self._currPos = -1
|
540
529
|
self._prevPos = -1
|
541
|
-
|
542
530
|
return
|
543
531
|
|
544
|
-
def clear(self):
|
545
|
-
"""Clear the view history.
|
546
|
-
"""
|
532
|
+
def clear(self) -> None:
|
533
|
+
"""Clear the view history."""
|
547
534
|
logger.debug("View history cleared")
|
548
535
|
self._navHistory = []
|
549
536
|
self._posHistory = []
|
@@ -551,7 +538,7 @@ class GuiDocViewHistory:
|
|
551
538
|
self._prevPos = -1
|
552
539
|
return
|
553
540
|
|
554
|
-
def append(self, tHandle):
|
541
|
+
def append(self, tHandle: str) -> bool:
|
555
542
|
"""Append a document handle and its scroll bar position to the
|
556
543
|
history, but only if the document is different than the current
|
557
544
|
active entry. Any further entries are truncated.
|
@@ -577,78 +564,65 @@ class GuiDocViewHistory:
|
|
577
564
|
|
578
565
|
return True
|
579
566
|
|
580
|
-
def forward(self):
|
581
|
-
"""Navigate to the next entry in the view history.
|
582
|
-
"""
|
567
|
+
def forward(self) -> None:
|
568
|
+
"""Navigate to the next entry in the view history."""
|
583
569
|
newPos = self._currPos + 1
|
584
570
|
if newPos < len(self._navHistory):
|
585
571
|
logger.debug("Move forward in view history")
|
586
572
|
self._prevPos = self._currPos
|
587
573
|
self._updateScrollBar()
|
588
|
-
|
589
574
|
self.docViewer.loadText(self._navHistory[newPos], updateHistory=False)
|
590
575
|
self.docViewer.setScrollPosition(self._posHistory[newPos])
|
591
576
|
self._currPos = newPos
|
592
577
|
self._updateNavButtons()
|
593
|
-
|
594
578
|
self._dumpHistory()
|
595
|
-
|
596
579
|
return
|
597
580
|
|
598
|
-
def backward(self):
|
599
|
-
"""Navigate to the previous entry in the view history.
|
600
|
-
"""
|
581
|
+
def backward(self) -> None:
|
582
|
+
"""Navigate to the previous entry in the view history."""
|
601
583
|
newPos = self._currPos - 1
|
602
584
|
if newPos >= 0:
|
603
585
|
logger.debug("Move backward in view history")
|
604
586
|
self._prevPos = self._currPos
|
605
587
|
self._updateScrollBar()
|
606
|
-
|
607
588
|
self.docViewer.loadText(self._navHistory[newPos], updateHistory=False)
|
608
589
|
self.docViewer.setScrollPosition(self._posHistory[newPos])
|
609
590
|
self._currPos = newPos
|
610
591
|
self._updateNavButtons()
|
611
|
-
|
612
592
|
self._dumpHistory()
|
613
|
-
|
614
593
|
return
|
615
594
|
|
616
595
|
##
|
617
596
|
# Internal Functions
|
618
597
|
##
|
619
598
|
|
620
|
-
def _updateScrollBar(self):
|
621
|
-
"""Update the scrollbar position of the previous entry.
|
622
|
-
"""
|
599
|
+
def _updateScrollBar(self) -> None:
|
600
|
+
"""Update the scrollbar position of the previous entry."""
|
623
601
|
if self._prevPos >= 0 and self._prevPos < len(self._posHistory):
|
624
602
|
self._posHistory[self._prevPos] = self.docViewer.scrollPosition
|
625
603
|
return
|
626
604
|
|
627
|
-
def _updateNavButtons(self):
|
628
|
-
"""Update the navigation buttons in the document header.
|
629
|
-
"""
|
605
|
+
def _updateNavButtons(self) -> None:
|
606
|
+
"""Update the navigation buttons in the document header."""
|
630
607
|
self.docViewer.docHeader.updateNavButtons(0, len(self._navHistory) - 1, self._currPos)
|
631
608
|
return
|
632
609
|
|
633
|
-
def _truncateHistory(self, atPos):
|
610
|
+
def _truncateHistory(self, atPos: int) -> None:
|
634
611
|
"""Truncate the navigation history to the given position. Also
|
635
612
|
enforces a maximum length of the navigation history to 20.
|
636
613
|
"""
|
637
614
|
nSkip = 1 if atPos > 19 else 0
|
638
|
-
|
639
615
|
self._navHistory = self._navHistory[nSkip:atPos + 1]
|
640
616
|
self._posHistory = self._posHistory[nSkip:atPos + 1]
|
641
|
-
|
642
617
|
self._currPos -= nSkip
|
643
618
|
self._prevPos -= nSkip
|
644
|
-
|
645
619
|
return
|
646
620
|
|
647
|
-
def _dumpHistory(self):
|
621
|
+
def _dumpHistory(self) -> None:
|
648
622
|
"""Debug function to dump history to the logger. Since it is a
|
649
623
|
for loop, it is skipped entirely if log level isn't DEBUG.
|
650
624
|
"""
|
651
|
-
if
|
625
|
+
if CONFIG.isDebug: # pragma: no cover
|
652
626
|
for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
|
653
627
|
logger.debug(
|
654
628
|
"History %02d: %s %13s [x:%d]" % (
|
@@ -667,7 +641,7 @@ class GuiDocViewHistory:
|
|
667
641
|
|
668
642
|
class GuiDocViewHeader(QWidget):
|
669
643
|
|
670
|
-
def __init__(self, docViewer):
|
644
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
671
645
|
super().__init__(parent=docViewer)
|
672
646
|
|
673
647
|
logger.debug("Create: GuiDocViewHeader")
|
@@ -685,25 +659,25 @@ class GuiDocViewHeader(QWidget):
|
|
685
659
|
self.setAutoFillBackground(True)
|
686
660
|
|
687
661
|
# Title Label
|
688
|
-
self.
|
689
|
-
self.
|
690
|
-
self.
|
691
|
-
self.
|
692
|
-
self.
|
693
|
-
self.
|
694
|
-
self.
|
695
|
-
self.
|
696
|
-
|
697
|
-
lblFont = self.
|
662
|
+
self.docTitle = QLabel()
|
663
|
+
self.docTitle.setText("")
|
664
|
+
self.docTitle.setIndent(0)
|
665
|
+
self.docTitle.setMargin(0)
|
666
|
+
self.docTitle.setContentsMargins(0, 0, 0, 0)
|
667
|
+
self.docTitle.setAutoFillBackground(True)
|
668
|
+
self.docTitle.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop)
|
669
|
+
self.docTitle.setFixedHeight(fPx)
|
670
|
+
|
671
|
+
lblFont = self.docTitle.font()
|
698
672
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
699
|
-
self.
|
673
|
+
self.docTitle.setFont(lblFont)
|
700
674
|
|
701
675
|
# Buttons
|
702
676
|
self.backButton = QToolButton(self)
|
703
677
|
self.backButton.setContentsMargins(0, 0, 0, 0)
|
704
678
|
self.backButton.setIconSize(QSize(fPx, fPx))
|
705
679
|
self.backButton.setFixedSize(fPx, fPx)
|
706
|
-
self.backButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
680
|
+
self.backButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
707
681
|
self.backButton.setVisible(False)
|
708
682
|
self.backButton.setToolTip(self.tr("Go Backward"))
|
709
683
|
self.backButton.clicked.connect(self.docViewer.navBackward)
|
@@ -712,7 +686,7 @@ class GuiDocViewHeader(QWidget):
|
|
712
686
|
self.forwardButton.setContentsMargins(0, 0, 0, 0)
|
713
687
|
self.forwardButton.setIconSize(QSize(fPx, fPx))
|
714
688
|
self.forwardButton.setFixedSize(fPx, fPx)
|
715
|
-
self.forwardButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
689
|
+
self.forwardButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
716
690
|
self.forwardButton.setVisible(False)
|
717
691
|
self.forwardButton.setToolTip(self.tr("Go Forward"))
|
718
692
|
self.forwardButton.clicked.connect(self.docViewer.navForward)
|
@@ -721,7 +695,7 @@ class GuiDocViewHeader(QWidget):
|
|
721
695
|
self.refreshButton.setContentsMargins(0, 0, 0, 0)
|
722
696
|
self.refreshButton.setIconSize(QSize(fPx, fPx))
|
723
697
|
self.refreshButton.setFixedSize(fPx, fPx)
|
724
|
-
self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
698
|
+
self.refreshButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
725
699
|
self.refreshButton.setVisible(False)
|
726
700
|
self.refreshButton.setToolTip(self.tr("Reload"))
|
727
701
|
self.refreshButton.clicked.connect(self._refreshDocument)
|
@@ -730,7 +704,7 @@ class GuiDocViewHeader(QWidget):
|
|
730
704
|
self.closeButton.setContentsMargins(0, 0, 0, 0)
|
731
705
|
self.closeButton.setIconSize(QSize(fPx, fPx))
|
732
706
|
self.closeButton.setFixedSize(fPx, fPx)
|
733
|
-
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
707
|
+
self.closeButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
734
708
|
self.closeButton.setVisible(False)
|
735
709
|
self.closeButton.setToolTip(self.tr("Close"))
|
736
710
|
self.closeButton.clicked.connect(self._closeDocument)
|
@@ -740,7 +714,7 @@ class GuiDocViewHeader(QWidget):
|
|
740
714
|
self.outerBox.setSpacing(hSp)
|
741
715
|
self.outerBox.addWidget(self.backButton, 0)
|
742
716
|
self.outerBox.addWidget(self.forwardButton, 0)
|
743
|
-
self.outerBox.addWidget(self.
|
717
|
+
self.outerBox.addWidget(self.docTitle, 1)
|
744
718
|
self.outerBox.addWidget(self.refreshButton, 0)
|
745
719
|
self.outerBox.addWidget(self.closeButton, 0)
|
746
720
|
self.setLayout(self.outerBox)
|
@@ -763,9 +737,8 @@ class GuiDocViewHeader(QWidget):
|
|
763
737
|
# Methods
|
764
738
|
##
|
765
739
|
|
766
|
-
def updateTheme(self):
|
767
|
-
"""Update theme elements.
|
768
|
-
"""
|
740
|
+
def updateTheme(self) -> None:
|
741
|
+
"""Update theme elements."""
|
769
742
|
self.backButton.setIcon(SHARED.theme.getIcon("backward"))
|
770
743
|
self.forwardButton.setIcon(SHARED.theme.getIcon("forward"))
|
771
744
|
self.refreshButton.setIcon(SHARED.theme.getIcon("refresh"))
|
@@ -785,32 +758,30 @@ class GuiDocViewHeader(QWidget):
|
|
785
758
|
|
786
759
|
return
|
787
760
|
|
788
|
-
def matchColours(self):
|
761
|
+
def matchColours(self) -> None:
|
789
762
|
"""Update the colours of the widget to match those of the syntax
|
790
763
|
theme rather than the main GUI.
|
791
764
|
"""
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
self.setPalette(
|
798
|
-
self.theTitle.setPalette(thePalette)
|
799
|
-
|
765
|
+
palette = QPalette()
|
766
|
+
palette.setColor(QPalette.ColorRole.Window, QColor(*SHARED.theme.colBack))
|
767
|
+
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
768
|
+
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
769
|
+
self.setPalette(palette)
|
770
|
+
self.docTitle.setPalette(palette)
|
800
771
|
return
|
801
772
|
|
802
|
-
def setTitleFromHandle(self, tHandle):
|
773
|
+
def setTitleFromHandle(self, tHandle: str | None) -> None:
|
803
774
|
"""Sets the document title from the handle, or alternatively,
|
804
775
|
set the whole document path.
|
805
776
|
"""
|
806
777
|
self._docHandle = tHandle
|
807
778
|
if tHandle is None:
|
808
|
-
self.
|
779
|
+
self.docTitle.setText("")
|
809
780
|
self.backButton.setVisible(False)
|
810
781
|
self.forwardButton.setVisible(False)
|
811
782
|
self.closeButton.setVisible(False)
|
812
783
|
self.refreshButton.setVisible(False)
|
813
|
-
return
|
784
|
+
return
|
814
785
|
|
815
786
|
pTree = SHARED.project.tree
|
816
787
|
if CONFIG.showFullPath:
|
@@ -821,42 +792,37 @@ class GuiDocViewHeader(QWidget):
|
|
821
792
|
if nwItem is not None:
|
822
793
|
tTitle.append(nwItem.itemName)
|
823
794
|
sSep = " %s " % nwUnicode.U_RSAQUO
|
824
|
-
self.
|
795
|
+
self.docTitle.setText(sSep.join(tTitle))
|
825
796
|
else:
|
826
|
-
nwItem
|
827
|
-
|
828
|
-
return False
|
829
|
-
self.theTitle.setText(nwItem.itemName)
|
797
|
+
if nwItem := pTree[tHandle]:
|
798
|
+
self.docTitle.setText(nwItem.itemName)
|
830
799
|
|
831
800
|
self.backButton.setVisible(True)
|
832
801
|
self.forwardButton.setVisible(True)
|
833
802
|
self.closeButton.setVisible(True)
|
834
803
|
self.refreshButton.setVisible(True)
|
835
804
|
|
836
|
-
return
|
805
|
+
return
|
837
806
|
|
838
|
-
def updateNavButtons(self, firstIdx, lastIdx, currIdx):
|
839
|
-
"""Enable and disable nav buttons based on index in history.
|
840
|
-
"""
|
807
|
+
def updateNavButtons(self, firstIdx: int, lastIdx: int, currIdx: int) -> None:
|
808
|
+
"""Enable and disable nav buttons based on index in history."""
|
841
809
|
self.backButton.setEnabled(currIdx > firstIdx)
|
842
810
|
self.forwardButton.setEnabled(currIdx < lastIdx)
|
843
811
|
return
|
844
812
|
|
845
813
|
##
|
846
|
-
# Slots
|
814
|
+
# Private Slots
|
847
815
|
##
|
848
816
|
|
849
817
|
@pyqtSlot()
|
850
|
-
def _closeDocument(self):
|
851
|
-
"""Trigger the close editor/viewer on the main window.
|
852
|
-
"""
|
818
|
+
def _closeDocument(self) -> None:
|
819
|
+
"""Trigger the close editor/viewer on the main window."""
|
853
820
|
self.mainGui.closeDocViewer()
|
854
821
|
return
|
855
822
|
|
856
823
|
@pyqtSlot()
|
857
|
-
def _refreshDocument(self):
|
858
|
-
"""Reload the content of the document.
|
859
|
-
"""
|
824
|
+
def _refreshDocument(self) -> None:
|
825
|
+
"""Reload the content of the document."""
|
860
826
|
if self.docViewer.docHandle == self.mainGui.docEditor.docHandle:
|
861
827
|
self.mainGui.saveDocument()
|
862
828
|
self.docViewer.reloadText()
|
@@ -866,11 +832,12 @@ class GuiDocViewHeader(QWidget):
|
|
866
832
|
# Events
|
867
833
|
##
|
868
834
|
|
869
|
-
def mousePressEvent(self,
|
835
|
+
def mousePressEvent(self, event: QMouseEvent) -> None:
|
870
836
|
"""Capture a click on the title and ensure that the item is
|
871
837
|
selected in the project tree.
|
872
838
|
"""
|
873
|
-
|
839
|
+
if event.button() == Qt.MouseButton.LeftButton:
|
840
|
+
self.docViewer.requestProjectItemSelected.emit(self._docHandle, True)
|
874
841
|
return
|
875
842
|
|
876
843
|
# END Class GuiDocViewHeader
|
@@ -883,21 +850,19 @@ class GuiDocViewHeader(QWidget):
|
|
883
850
|
|
884
851
|
class GuiDocViewFooter(QWidget):
|
885
852
|
|
886
|
-
def __init__(self, docViewer):
|
853
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
887
854
|
super().__init__(parent=docViewer)
|
888
855
|
|
889
856
|
logger.debug("Create: GuiDocViewFooter")
|
890
857
|
|
891
858
|
self.docViewer = docViewer
|
892
859
|
self.mainGui = docViewer.mainGui
|
893
|
-
self.viewMeta = docViewer.mainGui.viewMeta
|
894
860
|
|
895
861
|
# Internal Variables
|
896
862
|
self._docHandle = None
|
897
863
|
|
898
864
|
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
899
|
-
|
900
|
-
hSp = CONFIG.pxInt(8)
|
865
|
+
hSp = CONFIG.pxInt(4)
|
901
866
|
|
902
867
|
# Main Widget Settings
|
903
868
|
self.setContentsMargins(0, 0, 0, 0)
|
@@ -905,101 +870,43 @@ class GuiDocViewFooter(QWidget):
|
|
905
870
|
|
906
871
|
# Show/Hide Details
|
907
872
|
self.showHide = QToolButton(self)
|
908
|
-
self.showHide.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
873
|
+
self.showHide.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
909
874
|
self.showHide.setIconSize(QSize(fPx, fPx))
|
910
|
-
self.showHide.
|
911
|
-
self.showHide.
|
912
|
-
self.showHide.setToolTip(self.tr("Show/hide the references panel"))
|
913
|
-
|
914
|
-
# Sticky Button
|
915
|
-
self.stickyRefs = QToolButton(self)
|
916
|
-
self.stickyRefs.setCheckable(True)
|
917
|
-
self.stickyRefs.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
918
|
-
self.stickyRefs.setIconSize(QSize(fPx, fPx))
|
919
|
-
self.stickyRefs.setFixedSize(QSize(fPx, fPx))
|
920
|
-
self.stickyRefs.toggled.connect(self._doToggleSticky)
|
921
|
-
self.stickyRefs.setToolTip(self.tr(
|
922
|
-
"Activate to freeze the content of the references panel when changing document"
|
923
|
-
))
|
875
|
+
self.showHide.clicked.connect(lambda: self.docViewer.togglePanelVisibility.emit())
|
876
|
+
self.showHide.setToolTip(self.tr("Show/Hide Viewer Panel"))
|
924
877
|
|
925
878
|
# Show Comments
|
926
879
|
self.showComments = QToolButton(self)
|
880
|
+
self.showComments.setText(self.tr("Comments"))
|
927
881
|
self.showComments.setCheckable(True)
|
928
882
|
self.showComments.setChecked(CONFIG.viewComments)
|
929
|
-
self.showComments.setToolButtonStyle(Qt.
|
883
|
+
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
930
884
|
self.showComments.setIconSize(QSize(fPx, fPx))
|
931
|
-
self.showComments.setFixedSize(QSize(fPx, fPx))
|
932
885
|
self.showComments.toggled.connect(self._doToggleComments)
|
933
|
-
self.showComments.setToolTip(self.tr("Show
|
886
|
+
self.showComments.setToolTip(self.tr("Show Comments"))
|
934
887
|
|
935
888
|
# Show Synopsis
|
936
889
|
self.showSynopsis = QToolButton(self)
|
890
|
+
self.showSynopsis.setText(self.tr("Synopsis"))
|
937
891
|
self.showSynopsis.setCheckable(True)
|
938
892
|
self.showSynopsis.setChecked(CONFIG.viewSynopsis)
|
939
|
-
self.showSynopsis.setToolButtonStyle(Qt.
|
893
|
+
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
940
894
|
self.showSynopsis.setIconSize(QSize(fPx, fPx))
|
941
|
-
self.showSynopsis.setFixedSize(QSize(fPx, fPx))
|
942
895
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
943
|
-
self.showSynopsis.setToolTip(self.tr("Show
|
944
|
-
|
945
|
-
# Labels
|
946
|
-
self.lblRefs = QLabel(self.tr("References"))
|
947
|
-
self.lblRefs.setBuddy(self.showHide)
|
948
|
-
self.lblRefs.setIndent(0)
|
949
|
-
self.lblRefs.setMargin(0)
|
950
|
-
self.lblRefs.setContentsMargins(0, 0, 0, 0)
|
951
|
-
self.lblRefs.setAutoFillBackground(True)
|
952
|
-
self.lblRefs.setFixedHeight(fPx)
|
953
|
-
self.lblRefs.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
954
|
-
|
955
|
-
self.lblSticky = QLabel(self.tr("Sticky"))
|
956
|
-
self.lblSticky.setBuddy(self.stickyRefs)
|
957
|
-
self.lblSticky.setIndent(0)
|
958
|
-
self.lblSticky.setMargin(0)
|
959
|
-
self.lblSticky.setContentsMargins(0, 0, 0, 0)
|
960
|
-
self.lblSticky.setAutoFillBackground(True)
|
961
|
-
self.lblSticky.setFixedHeight(fPx)
|
962
|
-
self.lblSticky.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
963
|
-
|
964
|
-
self.lblComments = QLabel(self.tr("Comments"))
|
965
|
-
self.lblComments.setBuddy(self.showComments)
|
966
|
-
self.lblComments.setIndent(0)
|
967
|
-
self.lblComments.setMargin(0)
|
968
|
-
self.lblComments.setContentsMargins(0, 0, 0, 0)
|
969
|
-
self.lblComments.setAutoFillBackground(True)
|
970
|
-
self.lblComments.setFixedHeight(fPx)
|
971
|
-
self.lblComments.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
972
|
-
|
973
|
-
self.lblSynopsis = QLabel(self.tr("Synopsis"))
|
974
|
-
self.lblSynopsis.setBuddy(self.showSynopsis)
|
975
|
-
self.lblSynopsis.setIndent(0)
|
976
|
-
self.lblSynopsis.setMargin(0)
|
977
|
-
self.lblSynopsis.setContentsMargins(0, 0, 0, 0)
|
978
|
-
self.lblSynopsis.setAutoFillBackground(True)
|
979
|
-
self.lblSynopsis.setFixedHeight(fPx)
|
980
|
-
self.lblSynopsis.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
896
|
+
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
981
897
|
|
982
898
|
lblFont = self.font()
|
983
899
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
984
|
-
self.
|
985
|
-
self.
|
986
|
-
self.lblComments.setFont(lblFont)
|
987
|
-
self.lblSynopsis.setFont(lblFont)
|
900
|
+
self.showComments.setFont(lblFont)
|
901
|
+
self.showSynopsis.setFont(lblFont)
|
988
902
|
|
989
903
|
# Assemble Layout
|
990
904
|
self.outerBox = QHBoxLayout()
|
991
|
-
self.outerBox.setSpacing(bSp)
|
992
905
|
self.outerBox.addWidget(self.showHide, 0)
|
993
|
-
self.outerBox.addWidget(self.lblRefs, 0)
|
994
|
-
self.outerBox.addSpacing(hSp)
|
995
|
-
self.outerBox.addWidget(self.stickyRefs, 0)
|
996
|
-
self.outerBox.addWidget(self.lblSticky, 0)
|
997
906
|
self.outerBox.addStretch(1)
|
998
907
|
self.outerBox.addWidget(self.showComments, 0)
|
999
|
-
self.outerBox.addWidget(self.lblComments, 0)
|
1000
|
-
self.outerBox.addSpacing(hSp)
|
1001
908
|
self.outerBox.addWidget(self.showSynopsis, 0)
|
1002
|
-
self.outerBox.
|
909
|
+
self.outerBox.setSpacing(hSp)
|
1003
910
|
self.setLayout(self.outerBox)
|
1004
911
|
|
1005
912
|
# Fix Margins and Size
|
@@ -1024,23 +931,19 @@ class GuiDocViewFooter(QWidget):
|
|
1024
931
|
"""Update theme elements."""
|
1025
932
|
# Icons
|
1026
933
|
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
1027
|
-
stickyIcon = SHARED.theme.getToggleIcon("sticky", (fPx, fPx))
|
1028
934
|
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx))
|
1029
935
|
|
1030
|
-
self.showHide.setIcon(SHARED.theme.getIcon("
|
1031
|
-
self.stickyRefs.setIcon(stickyIcon)
|
936
|
+
self.showHide.setIcon(SHARED.theme.getIcon("panel"))
|
1032
937
|
self.showComments.setIcon(bulletIcon)
|
1033
938
|
self.showSynopsis.setIcon(bulletIcon)
|
1034
939
|
|
1035
940
|
# StyleSheets
|
1036
|
-
|
1037
941
|
buttonStyle = (
|
1038
942
|
"QToolButton {{border: none; background: transparent;}} "
|
1039
943
|
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
|
1040
944
|
).format(*SHARED.theme.colText)
|
1041
945
|
|
1042
946
|
self.showHide.setStyleSheet(buttonStyle)
|
1043
|
-
self.stickyRefs.setStyleSheet(buttonStyle)
|
1044
947
|
self.showComments.setStyleSheet(buttonStyle)
|
1045
948
|
self.showSynopsis.setStyleSheet(buttonStyle)
|
1046
949
|
|
@@ -1048,138 +951,33 @@ class GuiDocViewFooter(QWidget):
|
|
1048
951
|
|
1049
952
|
return
|
1050
953
|
|
1051
|
-
def matchColours(self):
|
954
|
+
def matchColours(self) -> None:
|
1052
955
|
"""Update the colours of the widget to match those of the syntax
|
1053
956
|
theme rather than the main GUI.
|
1054
957
|
"""
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
self.setPalette(thePalette)
|
1061
|
-
self.lblRefs.setPalette(thePalette)
|
1062
|
-
self.lblSticky.setPalette(thePalette)
|
1063
|
-
self.lblComments.setPalette(thePalette)
|
1064
|
-
self.lblSynopsis.setPalette(thePalette)
|
1065
|
-
|
958
|
+
palette = QPalette()
|
959
|
+
palette.setColor(QPalette.ColorRole.Window, QColor(*SHARED.theme.colBack))
|
960
|
+
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
961
|
+
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
962
|
+
self.setPalette(palette)
|
1066
963
|
return
|
1067
964
|
|
1068
965
|
##
|
1069
|
-
# Slots
|
966
|
+
# Private Slots
|
1070
967
|
##
|
1071
968
|
|
1072
|
-
@pyqtSlot()
|
1073
|
-
def _doShowHide(self):
|
1074
|
-
"""Toggle the expand/collapse of the panel.
|
1075
|
-
"""
|
1076
|
-
isVisible = self.viewMeta.isVisible()
|
1077
|
-
self.viewMeta.setVisible(not isVisible)
|
1078
|
-
return
|
1079
|
-
|
1080
969
|
@pyqtSlot(bool)
|
1081
|
-
def
|
1082
|
-
"""Toggle the
|
1083
|
-
|
1084
|
-
logger.debug("Reference sticky is %s", str(theState))
|
1085
|
-
self.docViewer.stickyRef = theState
|
1086
|
-
if not theState and self.docViewer.docHandle is not None:
|
1087
|
-
self.viewMeta.refreshReferences(self.docViewer.docHandle)
|
1088
|
-
return
|
1089
|
-
|
1090
|
-
@pyqtSlot(bool)
|
1091
|
-
def _doToggleComments(self, theState):
|
1092
|
-
"""Toggle the view comment button and reload the document.
|
1093
|
-
"""
|
1094
|
-
CONFIG.viewComments = theState
|
970
|
+
def _doToggleComments(self, state: bool) -> None:
|
971
|
+
"""Toggle the view comment button and reload the document."""
|
972
|
+
CONFIG.viewComments = state
|
1095
973
|
self.docViewer.reloadText()
|
1096
974
|
return
|
1097
975
|
|
1098
976
|
@pyqtSlot(bool)
|
1099
|
-
def _doToggleSynopsis(self,
|
1100
|
-
"""Toggle the view synopsis button and reload the document.
|
1101
|
-
|
1102
|
-
CONFIG.viewSynopsis = theState
|
977
|
+
def _doToggleSynopsis(self, state: bool) -> None:
|
978
|
+
"""Toggle the view synopsis button and reload the document."""
|
979
|
+
CONFIG.viewSynopsis = state
|
1103
980
|
self.docViewer.reloadText()
|
1104
981
|
return
|
1105
982
|
|
1106
983
|
# END Class GuiDocViewFooter
|
1107
|
-
|
1108
|
-
|
1109
|
-
# =============================================================================================== #
|
1110
|
-
# The Document Back-Reference Panel
|
1111
|
-
# Placed in a separate QSplitter position in the main GUI window
|
1112
|
-
# =============================================================================================== #
|
1113
|
-
|
1114
|
-
class GuiDocViewDetails(QScrollArea):
|
1115
|
-
|
1116
|
-
def __init__(self, mainGui):
|
1117
|
-
super().__init__(parent=mainGui)
|
1118
|
-
|
1119
|
-
logger.debug("Create: GuiDocViewDetails")
|
1120
|
-
|
1121
|
-
self.mainGui = mainGui
|
1122
|
-
|
1123
|
-
self.refList = QLabel("")
|
1124
|
-
self.refList.setWordWrap(True)
|
1125
|
-
self.refList.setAlignment(Qt.AlignTop)
|
1126
|
-
self.refList.setScaledContents(True)
|
1127
|
-
self.refList.linkActivated.connect(self._linkClicked)
|
1128
|
-
|
1129
|
-
self.linkStyle = "style='color: rgb({0},{1},{2})'".format(*SHARED.theme.colLink)
|
1130
|
-
|
1131
|
-
# Assemble
|
1132
|
-
self.outerWidget = QWidget()
|
1133
|
-
self.outerBox = QHBoxLayout()
|
1134
|
-
self.outerBox.addWidget(self.refList, 1)
|
1135
|
-
|
1136
|
-
self.outerWidget.setLayout(self.outerBox)
|
1137
|
-
self.setWidget(self.outerWidget)
|
1138
|
-
|
1139
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
1140
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
1141
|
-
self.setWidgetResizable(True)
|
1142
|
-
self.setMinimumHeight(CONFIG.pxInt(50))
|
1143
|
-
self.setFrameStyle(QFrame.NoFrame)
|
1144
|
-
|
1145
|
-
logger.debug("Ready: GuiDocViewDetails")
|
1146
|
-
|
1147
|
-
return
|
1148
|
-
|
1149
|
-
def refreshReferences(self, tHandle):
|
1150
|
-
"""Update the current list of document references from the
|
1151
|
-
project index.
|
1152
|
-
"""
|
1153
|
-
if self.mainGui.docViewer.stickyRef:
|
1154
|
-
return
|
1155
|
-
|
1156
|
-
theRefs = SHARED.project.index.getBackReferenceList(tHandle)
|
1157
|
-
theList = []
|
1158
|
-
for tHandle in theRefs:
|
1159
|
-
tItem = SHARED.project.tree[tHandle]
|
1160
|
-
if tItem is not None:
|
1161
|
-
theList.append("<a href='%s#%s' %s>%s</a>" % (
|
1162
|
-
tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
|
1163
|
-
))
|
1164
|
-
|
1165
|
-
self.refList.setText(", ".join(theList))
|
1166
|
-
|
1167
|
-
return
|
1168
|
-
|
1169
|
-
##
|
1170
|
-
# Private Slots
|
1171
|
-
##
|
1172
|
-
|
1173
|
-
@pyqtSlot(str)
|
1174
|
-
def _linkClicked(self, theLink):
|
1175
|
-
"""Capture the link-click and forward it to the document viewer
|
1176
|
-
class for handling.
|
1177
|
-
"""
|
1178
|
-
logger.debug("Clicked link: '%s'", theLink)
|
1179
|
-
if len(theLink) >= 13:
|
1180
|
-
tHandle = theLink[:13]
|
1181
|
-
tAnchor = theLink[13:] or None
|
1182
|
-
self.mainGui.viewDocument(tHandle, tAnchor)
|
1183
|
-
return
|
1184
|
-
|
1185
|
-
# END Class GuiDocViewDetails
|