novelWriter 2.1.1__py3-none-any.whl → 2.2rc1__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.1.1.dist-info → novelWriter-2.2rc1.dist-info}/METADATA +3 -3
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/RECORD +105 -76
- novelwriter/__init__.py +6 -24
- novelwriter/assets/i18n/project_de_DE.json +10 -0
- novelwriter/assets/i18n/project_en_GB.json +11 -0
- novelwriter/assets/i18n/project_en_US.json +10 -0
- novelwriter/assets/i18n/project_ja_JP.json +11 -1
- novelwriter/assets/i18n/project_nb_NO.json +10 -0
- novelwriter/assets/i18n/project_nn_NO.json +10 -0
- novelwriter/assets/icons/novelwriter.ico +0 -0
- novelwriter/assets/icons/novelwriter.svg +8 -183
- novelwriter/assets/icons/typicons_dark/icons.conf +17 -2
- 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.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +8 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +8 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +5 -0
- novelwriter/assets/icons/typicons_dark/typ_eye.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +17 -2
- 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.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +8 -0
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +8 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +5 -0
- novelwriter/assets/icons/typicons_light/typ_eye.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +4 -0
- novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- novelwriter/assets/icons/x-novelwriter-project.svg +7 -206
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +7 -0
- novelwriter/assets/text/release_notes.htm +7 -37
- novelwriter/common.py +22 -1
- novelwriter/config.py +27 -42
- novelwriter/constants.py +45 -7
- novelwriter/core/buildsettings.py +40 -24
- novelwriter/core/coretools.py +8 -1
- novelwriter/core/docbuild.py +2 -6
- novelwriter/core/index.py +264 -175
- novelwriter/core/options.py +8 -3
- novelwriter/core/project.py +2 -2
- novelwriter/core/projectdata.py +3 -3
- novelwriter/core/tohtml.py +60 -59
- novelwriter/core/tokenizer.py +110 -70
- novelwriter/core/tomd.py +51 -38
- novelwriter/core/toodt.py +184 -147
- novelwriter/dialogs/preferences.py +75 -106
- novelwriter/dialogs/projsettings.py +101 -110
- novelwriter/dialogs/updates.py +25 -14
- novelwriter/enum.py +28 -3
- novelwriter/extensions/novelselector.py +1 -1
- novelwriter/gui/doceditor.py +1345 -1235
- novelwriter/gui/dochighlight.py +98 -62
- novelwriter/gui/docviewer.py +151 -340
- novelwriter/gui/docviewerpanel.py +457 -0
- novelwriter/gui/editordocument.py +126 -0
- novelwriter/gui/mainmenu.py +350 -300
- novelwriter/gui/noveltree.py +101 -125
- novelwriter/gui/outline.py +154 -171
- novelwriter/gui/projtree.py +480 -380
- novelwriter/gui/sidebar.py +106 -75
- novelwriter/gui/statusbar.py +1 -1
- novelwriter/gui/theme.py +114 -75
- novelwriter/guimain.py +353 -254
- novelwriter/shared.py +36 -3
- novelwriter/tools/dictionaries.py +268 -0
- novelwriter/tools/manusbuild.py +17 -6
- novelwriter/tools/manuscript.py +11 -3
- novelwriter/tools/manussettings.py +0 -14
- novelwriter/tools/projwizard.py +16 -2
- novelwriter/tools/writingstats.py +1 -1
- novelwriter/assets/icons/typicons_dark/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-menu.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-menu.svg +0 -4
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/WHEEL +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/top_level.txt +0 -0
novelwriter/gui/docviewer.py
CHANGED
@@ -4,7 +4,6 @@ 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
|
@@ -34,12 +33,12 @@ from typing import TYPE_CHECKING
|
|
34
33
|
|
35
34
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QPoint, QSize, Qt, QUrl
|
36
35
|
from PyQt5.QtGui import (
|
37
|
-
QColor, QCursor, QFont,
|
38
|
-
|
36
|
+
QColor, QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor,
|
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
|
@@ -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
|
@@ -383,9 +380,6 @@ class GuiDocViewer(QTextBrowser):
|
|
383
380
|
|
384
381
|
mnuContext = QMenu(self)
|
385
382
|
|
386
|
-
# Cut, Copy and Paste
|
387
|
-
# ===================
|
388
|
-
|
389
383
|
if userSelection:
|
390
384
|
mnuCopy = QAction(self.tr("Copy"), mnuContext)
|
391
385
|
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
@@ -393,22 +387,19 @@ class GuiDocViewer(QTextBrowser):
|
|
393
387
|
|
394
388
|
mnuContext.addSeparator()
|
395
389
|
|
396
|
-
# Selections
|
397
|
-
# ==========
|
398
|
-
|
399
390
|
mnuSelAll = QAction(self.tr("Select All"), mnuContext)
|
400
391
|
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
401
392
|
mnuContext.addAction(mnuSelAll)
|
402
393
|
|
403
394
|
mnuSelWord = QAction(self.tr("Select Word"), mnuContext)
|
404
395
|
mnuSelWord.triggered.connect(
|
405
|
-
lambda: self._makePosSelection(QTextCursor.WordUnderCursor, point)
|
396
|
+
lambda: self._makePosSelection(QTextCursor.SelectionType.WordUnderCursor, point)
|
406
397
|
)
|
407
398
|
mnuContext.addAction(mnuSelWord)
|
408
399
|
|
409
400
|
mnuSelPara = QAction(self.tr("Select Paragraph"), mnuContext)
|
410
401
|
mnuSelPara.triggered.connect(
|
411
|
-
lambda: self._makePosSelection(QTextCursor.BlockUnderCursor, point)
|
402
|
+
lambda: self._makePosSelection(QTextCursor.SelectionType.BlockUnderCursor, point)
|
412
403
|
)
|
413
404
|
mnuContext.addAction(mnuSelPara)
|
414
405
|
|
@@ -429,9 +420,9 @@ class GuiDocViewer(QTextBrowser):
|
|
429
420
|
|
430
421
|
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
|
431
422
|
"""Capture mouse click events on the document."""
|
432
|
-
if event.button() == Qt.BackButton:
|
423
|
+
if event.button() == Qt.MouseButton.BackButton:
|
433
424
|
self.navBackward()
|
434
|
-
elif event.button() == Qt.ForwardButton:
|
425
|
+
elif event.button() == Qt.MouseButton.ForwardButton:
|
435
426
|
self.navForward()
|
436
427
|
else:
|
437
428
|
super().mouseReleaseEvent(event)
|
@@ -442,29 +433,28 @@ class GuiDocViewer(QTextBrowser):
|
|
442
433
|
##
|
443
434
|
|
444
435
|
def _makeSelection(self, selType: QTextCursor.SelectionType) -> None:
|
445
|
-
"""Handle
|
446
|
-
|
447
|
-
|
448
|
-
|
436
|
+
"""Handle selection of text based on a selection mode."""
|
437
|
+
cursor = self.textCursor()
|
438
|
+
cursor.clearSelection()
|
439
|
+
cursor.select(selType)
|
449
440
|
|
450
|
-
if selType == QTextCursor.BlockUnderCursor:
|
441
|
+
if selType == QTextCursor.SelectionType.BlockUnderCursor:
|
451
442
|
# This selection mode also selects the preceding paragraph
|
452
443
|
# separator, which we want to avoid.
|
453
|
-
posS =
|
454
|
-
posE =
|
455
|
-
selTxt =
|
444
|
+
posS = cursor.selectionStart()
|
445
|
+
posE = cursor.selectionEnd()
|
446
|
+
selTxt = cursor.selectedText()
|
456
447
|
if selTxt.startswith(nwUnicode.U_PSEP):
|
457
|
-
|
458
|
-
|
448
|
+
cursor.setPosition(posS+1, QTextCursor.MoveMode.MoveAnchor)
|
449
|
+
cursor.setPosition(posE, QTextCursor.MoveMode.KeepAnchor)
|
459
450
|
|
460
|
-
self.setTextCursor(
|
451
|
+
self.setTextCursor(cursor)
|
461
452
|
|
462
453
|
return
|
463
454
|
|
464
455
|
def _makePosSelection(self, selType: QTextCursor.SelectionType, pos: QPoint) -> None:
|
465
456
|
"""Handle text selection at a given location."""
|
466
|
-
|
467
|
-
self.setTextCursor(theCursor)
|
457
|
+
self.setTextCursor(self.cursorForPosition(pos))
|
468
458
|
self._makeSelection(selType)
|
469
459
|
return
|
470
460
|
|
@@ -530,20 +520,16 @@ class GuiDocViewer(QTextBrowser):
|
|
530
520
|
|
531
521
|
class GuiDocViewHistory:
|
532
522
|
|
533
|
-
def __init__(self, docViewer):
|
534
|
-
|
523
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
535
524
|
self.docViewer = docViewer
|
536
|
-
|
537
525
|
self._navHistory = []
|
538
526
|
self._posHistory = []
|
539
527
|
self._currPos = -1
|
540
528
|
self._prevPos = -1
|
541
|
-
|
542
529
|
return
|
543
530
|
|
544
|
-
def clear(self):
|
545
|
-
"""Clear the view history.
|
546
|
-
"""
|
531
|
+
def clear(self) -> None:
|
532
|
+
"""Clear the view history."""
|
547
533
|
logger.debug("View history cleared")
|
548
534
|
self._navHistory = []
|
549
535
|
self._posHistory = []
|
@@ -551,7 +537,7 @@ class GuiDocViewHistory:
|
|
551
537
|
self._prevPos = -1
|
552
538
|
return
|
553
539
|
|
554
|
-
def append(self, tHandle):
|
540
|
+
def append(self, tHandle: str) -> bool:
|
555
541
|
"""Append a document handle and its scroll bar position to the
|
556
542
|
history, but only if the document is different than the current
|
557
543
|
active entry. Any further entries are truncated.
|
@@ -577,78 +563,65 @@ class GuiDocViewHistory:
|
|
577
563
|
|
578
564
|
return True
|
579
565
|
|
580
|
-
def forward(self):
|
581
|
-
"""Navigate to the next entry in the view history.
|
582
|
-
"""
|
566
|
+
def forward(self) -> None:
|
567
|
+
"""Navigate to the next entry in the view history."""
|
583
568
|
newPos = self._currPos + 1
|
584
569
|
if newPos < len(self._navHistory):
|
585
570
|
logger.debug("Move forward in view history")
|
586
571
|
self._prevPos = self._currPos
|
587
572
|
self._updateScrollBar()
|
588
|
-
|
589
573
|
self.docViewer.loadText(self._navHistory[newPos], updateHistory=False)
|
590
574
|
self.docViewer.setScrollPosition(self._posHistory[newPos])
|
591
575
|
self._currPos = newPos
|
592
576
|
self._updateNavButtons()
|
593
|
-
|
594
577
|
self._dumpHistory()
|
595
|
-
|
596
578
|
return
|
597
579
|
|
598
|
-
def backward(self):
|
599
|
-
"""Navigate to the previous entry in the view history.
|
600
|
-
"""
|
580
|
+
def backward(self) -> None:
|
581
|
+
"""Navigate to the previous entry in the view history."""
|
601
582
|
newPos = self._currPos - 1
|
602
583
|
if newPos >= 0:
|
603
584
|
logger.debug("Move backward in view history")
|
604
585
|
self._prevPos = self._currPos
|
605
586
|
self._updateScrollBar()
|
606
|
-
|
607
587
|
self.docViewer.loadText(self._navHistory[newPos], updateHistory=False)
|
608
588
|
self.docViewer.setScrollPosition(self._posHistory[newPos])
|
609
589
|
self._currPos = newPos
|
610
590
|
self._updateNavButtons()
|
611
|
-
|
612
591
|
self._dumpHistory()
|
613
|
-
|
614
592
|
return
|
615
593
|
|
616
594
|
##
|
617
595
|
# Internal Functions
|
618
596
|
##
|
619
597
|
|
620
|
-
def _updateScrollBar(self):
|
621
|
-
"""Update the scrollbar position of the previous entry.
|
622
|
-
"""
|
598
|
+
def _updateScrollBar(self) -> None:
|
599
|
+
"""Update the scrollbar position of the previous entry."""
|
623
600
|
if self._prevPos >= 0 and self._prevPos < len(self._posHistory):
|
624
601
|
self._posHistory[self._prevPos] = self.docViewer.scrollPosition
|
625
602
|
return
|
626
603
|
|
627
|
-
def _updateNavButtons(self):
|
628
|
-
"""Update the navigation buttons in the document header.
|
629
|
-
"""
|
604
|
+
def _updateNavButtons(self) -> None:
|
605
|
+
"""Update the navigation buttons in the document header."""
|
630
606
|
self.docViewer.docHeader.updateNavButtons(0, len(self._navHistory) - 1, self._currPos)
|
631
607
|
return
|
632
608
|
|
633
|
-
def _truncateHistory(self, atPos):
|
609
|
+
def _truncateHistory(self, atPos: int) -> None:
|
634
610
|
"""Truncate the navigation history to the given position. Also
|
635
611
|
enforces a maximum length of the navigation history to 20.
|
636
612
|
"""
|
637
613
|
nSkip = 1 if atPos > 19 else 0
|
638
|
-
|
639
614
|
self._navHistory = self._navHistory[nSkip:atPos + 1]
|
640
615
|
self._posHistory = self._posHistory[nSkip:atPos + 1]
|
641
|
-
|
642
616
|
self._currPos -= nSkip
|
643
617
|
self._prevPos -= nSkip
|
644
|
-
|
645
618
|
return
|
646
619
|
|
647
|
-
def _dumpHistory(self):
|
620
|
+
def _dumpHistory(self) -> None:
|
648
621
|
"""Debug function to dump history to the logger. Since it is a
|
649
622
|
for loop, it is skipped entirely if log level isn't DEBUG.
|
650
623
|
"""
|
651
|
-
if
|
624
|
+
if CONFIG.isDebug: # pragma: no cover
|
652
625
|
for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
|
653
626
|
logger.debug(
|
654
627
|
"History %02d: %s %13s [x:%d]" % (
|
@@ -667,7 +640,7 @@ class GuiDocViewHistory:
|
|
667
640
|
|
668
641
|
class GuiDocViewHeader(QWidget):
|
669
642
|
|
670
|
-
def __init__(self, docViewer):
|
643
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
671
644
|
super().__init__(parent=docViewer)
|
672
645
|
|
673
646
|
logger.debug("Create: GuiDocViewHeader")
|
@@ -685,54 +658,54 @@ class GuiDocViewHeader(QWidget):
|
|
685
658
|
self.setAutoFillBackground(True)
|
686
659
|
|
687
660
|
# Title Label
|
688
|
-
self.
|
689
|
-
self.
|
690
|
-
self.
|
691
|
-
self.
|
692
|
-
self.
|
693
|
-
self.
|
694
|
-
self.
|
695
|
-
self.
|
696
|
-
|
697
|
-
lblFont = self.
|
661
|
+
self.docTitle = QLabel()
|
662
|
+
self.docTitle.setText("")
|
663
|
+
self.docTitle.setIndent(0)
|
664
|
+
self.docTitle.setMargin(0)
|
665
|
+
self.docTitle.setContentsMargins(0, 0, 0, 0)
|
666
|
+
self.docTitle.setAutoFillBackground(True)
|
667
|
+
self.docTitle.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop)
|
668
|
+
self.docTitle.setFixedHeight(fPx)
|
669
|
+
|
670
|
+
lblFont = self.docTitle.font()
|
698
671
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
699
|
-
self.
|
672
|
+
self.docTitle.setFont(lblFont)
|
700
673
|
|
701
674
|
# Buttons
|
702
675
|
self.backButton = QToolButton(self)
|
703
676
|
self.backButton.setContentsMargins(0, 0, 0, 0)
|
704
677
|
self.backButton.setIconSize(QSize(fPx, fPx))
|
705
678
|
self.backButton.setFixedSize(fPx, fPx)
|
706
|
-
self.backButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
679
|
+
self.backButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
707
680
|
self.backButton.setVisible(False)
|
708
|
-
self.backButton.setToolTip(self.tr("Go
|
681
|
+
self.backButton.setToolTip(self.tr("Go Backward"))
|
709
682
|
self.backButton.clicked.connect(self.docViewer.navBackward)
|
710
683
|
|
711
684
|
self.forwardButton = QToolButton(self)
|
712
685
|
self.forwardButton.setContentsMargins(0, 0, 0, 0)
|
713
686
|
self.forwardButton.setIconSize(QSize(fPx, fPx))
|
714
687
|
self.forwardButton.setFixedSize(fPx, fPx)
|
715
|
-
self.forwardButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
688
|
+
self.forwardButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
716
689
|
self.forwardButton.setVisible(False)
|
717
|
-
self.forwardButton.setToolTip(self.tr("Go
|
690
|
+
self.forwardButton.setToolTip(self.tr("Go Forward"))
|
718
691
|
self.forwardButton.clicked.connect(self.docViewer.navForward)
|
719
692
|
|
720
693
|
self.refreshButton = QToolButton(self)
|
721
694
|
self.refreshButton.setContentsMargins(0, 0, 0, 0)
|
722
695
|
self.refreshButton.setIconSize(QSize(fPx, fPx))
|
723
696
|
self.refreshButton.setFixedSize(fPx, fPx)
|
724
|
-
self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
697
|
+
self.refreshButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
725
698
|
self.refreshButton.setVisible(False)
|
726
|
-
self.refreshButton.setToolTip(self.tr("Reload
|
699
|
+
self.refreshButton.setToolTip(self.tr("Reload"))
|
727
700
|
self.refreshButton.clicked.connect(self._refreshDocument)
|
728
701
|
|
729
702
|
self.closeButton = QToolButton(self)
|
730
703
|
self.closeButton.setContentsMargins(0, 0, 0, 0)
|
731
704
|
self.closeButton.setIconSize(QSize(fPx, fPx))
|
732
705
|
self.closeButton.setFixedSize(fPx, fPx)
|
733
|
-
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
706
|
+
self.closeButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
734
707
|
self.closeButton.setVisible(False)
|
735
|
-
self.closeButton.setToolTip(self.tr("Close
|
708
|
+
self.closeButton.setToolTip(self.tr("Close"))
|
736
709
|
self.closeButton.clicked.connect(self._closeDocument)
|
737
710
|
|
738
711
|
# Assemble Layout
|
@@ -740,7 +713,7 @@ class GuiDocViewHeader(QWidget):
|
|
740
713
|
self.outerBox.setSpacing(hSp)
|
741
714
|
self.outerBox.addWidget(self.backButton, 0)
|
742
715
|
self.outerBox.addWidget(self.forwardButton, 0)
|
743
|
-
self.outerBox.addWidget(self.
|
716
|
+
self.outerBox.addWidget(self.docTitle, 1)
|
744
717
|
self.outerBox.addWidget(self.refreshButton, 0)
|
745
718
|
self.outerBox.addWidget(self.closeButton, 0)
|
746
719
|
self.setLayout(self.outerBox)
|
@@ -763,9 +736,8 @@ class GuiDocViewHeader(QWidget):
|
|
763
736
|
# Methods
|
764
737
|
##
|
765
738
|
|
766
|
-
def updateTheme(self):
|
767
|
-
"""Update theme elements.
|
768
|
-
"""
|
739
|
+
def updateTheme(self) -> None:
|
740
|
+
"""Update theme elements."""
|
769
741
|
self.backButton.setIcon(SHARED.theme.getIcon("backward"))
|
770
742
|
self.forwardButton.setIcon(SHARED.theme.getIcon("forward"))
|
771
743
|
self.refreshButton.setIcon(SHARED.theme.getIcon("refresh"))
|
@@ -785,32 +757,30 @@ class GuiDocViewHeader(QWidget):
|
|
785
757
|
|
786
758
|
return
|
787
759
|
|
788
|
-
def matchColours(self):
|
760
|
+
def matchColours(self) -> None:
|
789
761
|
"""Update the colours of the widget to match those of the syntax
|
790
762
|
theme rather than the main GUI.
|
791
763
|
"""
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
self.setPalette(
|
798
|
-
self.theTitle.setPalette(thePalette)
|
799
|
-
|
764
|
+
palette = QPalette()
|
765
|
+
palette.setColor(QPalette.ColorRole.Window, QColor(*SHARED.theme.colBack))
|
766
|
+
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
767
|
+
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
768
|
+
self.setPalette(palette)
|
769
|
+
self.docTitle.setPalette(palette)
|
800
770
|
return
|
801
771
|
|
802
|
-
def setTitleFromHandle(self, tHandle):
|
772
|
+
def setTitleFromHandle(self, tHandle: str | None) -> None:
|
803
773
|
"""Sets the document title from the handle, or alternatively,
|
804
774
|
set the whole document path.
|
805
775
|
"""
|
806
776
|
self._docHandle = tHandle
|
807
777
|
if tHandle is None:
|
808
|
-
self.
|
778
|
+
self.docTitle.setText("")
|
809
779
|
self.backButton.setVisible(False)
|
810
780
|
self.forwardButton.setVisible(False)
|
811
781
|
self.closeButton.setVisible(False)
|
812
782
|
self.refreshButton.setVisible(False)
|
813
|
-
return
|
783
|
+
return
|
814
784
|
|
815
785
|
pTree = SHARED.project.tree
|
816
786
|
if CONFIG.showFullPath:
|
@@ -821,42 +791,37 @@ class GuiDocViewHeader(QWidget):
|
|
821
791
|
if nwItem is not None:
|
822
792
|
tTitle.append(nwItem.itemName)
|
823
793
|
sSep = " %s " % nwUnicode.U_RSAQUO
|
824
|
-
self.
|
794
|
+
self.docTitle.setText(sSep.join(tTitle))
|
825
795
|
else:
|
826
|
-
nwItem
|
827
|
-
|
828
|
-
return False
|
829
|
-
self.theTitle.setText(nwItem.itemName)
|
796
|
+
if nwItem := pTree[tHandle]:
|
797
|
+
self.docTitle.setText(nwItem.itemName)
|
830
798
|
|
831
799
|
self.backButton.setVisible(True)
|
832
800
|
self.forwardButton.setVisible(True)
|
833
801
|
self.closeButton.setVisible(True)
|
834
802
|
self.refreshButton.setVisible(True)
|
835
803
|
|
836
|
-
return
|
804
|
+
return
|
837
805
|
|
838
|
-
def updateNavButtons(self, firstIdx, lastIdx, currIdx):
|
839
|
-
"""Enable and disable nav buttons based on index in history.
|
840
|
-
"""
|
806
|
+
def updateNavButtons(self, firstIdx: int, lastIdx: int, currIdx: int) -> None:
|
807
|
+
"""Enable and disable nav buttons based on index in history."""
|
841
808
|
self.backButton.setEnabled(currIdx > firstIdx)
|
842
809
|
self.forwardButton.setEnabled(currIdx < lastIdx)
|
843
810
|
return
|
844
811
|
|
845
812
|
##
|
846
|
-
# Slots
|
813
|
+
# Private Slots
|
847
814
|
##
|
848
815
|
|
849
816
|
@pyqtSlot()
|
850
|
-
def _closeDocument(self):
|
851
|
-
"""Trigger the close editor/viewer on the main window.
|
852
|
-
"""
|
817
|
+
def _closeDocument(self) -> None:
|
818
|
+
"""Trigger the close editor/viewer on the main window."""
|
853
819
|
self.mainGui.closeDocViewer()
|
854
820
|
return
|
855
821
|
|
856
822
|
@pyqtSlot()
|
857
|
-
def _refreshDocument(self):
|
858
|
-
"""Reload the content of the document.
|
859
|
-
"""
|
823
|
+
def _refreshDocument(self) -> None:
|
824
|
+
"""Reload the content of the document."""
|
860
825
|
if self.docViewer.docHandle == self.mainGui.docEditor.docHandle:
|
861
826
|
self.mainGui.saveDocument()
|
862
827
|
self.docViewer.reloadText()
|
@@ -866,11 +831,12 @@ class GuiDocViewHeader(QWidget):
|
|
866
831
|
# Events
|
867
832
|
##
|
868
833
|
|
869
|
-
def mousePressEvent(self,
|
834
|
+
def mousePressEvent(self, event: QMouseEvent) -> None:
|
870
835
|
"""Capture a click on the title and ensure that the item is
|
871
836
|
selected in the project tree.
|
872
837
|
"""
|
873
|
-
|
838
|
+
if event.button() == Qt.MouseButton.LeftButton:
|
839
|
+
self.docViewer.requestProjectItemSelected.emit(self._docHandle, True)
|
874
840
|
return
|
875
841
|
|
876
842
|
# END Class GuiDocViewHeader
|
@@ -883,14 +849,13 @@ class GuiDocViewHeader(QWidget):
|
|
883
849
|
|
884
850
|
class GuiDocViewFooter(QWidget):
|
885
851
|
|
886
|
-
def __init__(self, docViewer):
|
852
|
+
def __init__(self, docViewer: GuiDocViewer) -> None:
|
887
853
|
super().__init__(parent=docViewer)
|
888
854
|
|
889
855
|
logger.debug("Create: GuiDocViewFooter")
|
890
856
|
|
891
857
|
self.docViewer = docViewer
|
892
858
|
self.mainGui = docViewer.mainGui
|
893
|
-
self.viewMeta = docViewer.mainGui.viewMeta
|
894
859
|
|
895
860
|
# Internal Variables
|
896
861
|
self._docHandle = None
|
@@ -905,62 +870,33 @@ 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
875
|
self.showHide.setFixedSize(QSize(fPx, fPx))
|
911
|
-
self.showHide.clicked.connect(self.
|
912
|
-
self.showHide.setToolTip(self.tr("Show/
|
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
|
-
))
|
876
|
+
self.showHide.clicked.connect(lambda: self.docViewer.togglePanelVisibility.emit())
|
877
|
+
self.showHide.setToolTip(self.tr("Show/Hide Viewer Panel"))
|
924
878
|
|
925
879
|
# Show Comments
|
926
880
|
self.showComments = QToolButton(self)
|
927
881
|
self.showComments.setCheckable(True)
|
928
882
|
self.showComments.setChecked(CONFIG.viewComments)
|
929
|
-
self.showComments.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
883
|
+
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
930
884
|
self.showComments.setIconSize(QSize(fPx, fPx))
|
931
885
|
self.showComments.setFixedSize(QSize(fPx, fPx))
|
932
886
|
self.showComments.toggled.connect(self._doToggleComments)
|
933
|
-
self.showComments.setToolTip(self.tr("Show
|
887
|
+
self.showComments.setToolTip(self.tr("Show Comments"))
|
934
888
|
|
935
889
|
# Show Synopsis
|
936
890
|
self.showSynopsis = QToolButton(self)
|
937
891
|
self.showSynopsis.setCheckable(True)
|
938
892
|
self.showSynopsis.setChecked(CONFIG.viewSynopsis)
|
939
|
-
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
893
|
+
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
940
894
|
self.showSynopsis.setIconSize(QSize(fPx, fPx))
|
941
895
|
self.showSynopsis.setFixedSize(QSize(fPx, fPx))
|
942
896
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
943
|
-
self.showSynopsis.setToolTip(self.tr("Show
|
897
|
+
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
944
898
|
|
945
899
|
# 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
900
|
self.lblComments = QLabel(self.tr("Comments"))
|
965
901
|
self.lblComments.setBuddy(self.showComments)
|
966
902
|
self.lblComments.setIndent(0)
|
@@ -968,7 +904,7 @@ class GuiDocViewFooter(QWidget):
|
|
968
904
|
self.lblComments.setContentsMargins(0, 0, 0, 0)
|
969
905
|
self.lblComments.setAutoFillBackground(True)
|
970
906
|
self.lblComments.setFixedHeight(fPx)
|
971
|
-
self.lblComments.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
907
|
+
self.lblComments.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
972
908
|
|
973
909
|
self.lblSynopsis = QLabel(self.tr("Synopsis"))
|
974
910
|
self.lblSynopsis.setBuddy(self.showSynopsis)
|
@@ -977,12 +913,10 @@ class GuiDocViewFooter(QWidget):
|
|
977
913
|
self.lblSynopsis.setContentsMargins(0, 0, 0, 0)
|
978
914
|
self.lblSynopsis.setAutoFillBackground(True)
|
979
915
|
self.lblSynopsis.setFixedHeight(fPx)
|
980
|
-
self.lblSynopsis.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
916
|
+
self.lblSynopsis.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
981
917
|
|
982
918
|
lblFont = self.font()
|
983
919
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
984
|
-
self.lblRefs.setFont(lblFont)
|
985
|
-
self.lblSticky.setFont(lblFont)
|
986
920
|
self.lblComments.setFont(lblFont)
|
987
921
|
self.lblSynopsis.setFont(lblFont)
|
988
922
|
|
@@ -990,10 +924,6 @@ class GuiDocViewFooter(QWidget):
|
|
990
924
|
self.outerBox = QHBoxLayout()
|
991
925
|
self.outerBox.setSpacing(bSp)
|
992
926
|
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
927
|
self.outerBox.addStretch(1)
|
998
928
|
self.outerBox.addWidget(self.showComments, 0)
|
999
929
|
self.outerBox.addWidget(self.lblComments, 0)
|
@@ -1020,39 +950,23 @@ class GuiDocViewFooter(QWidget):
|
|
1020
950
|
# Methods
|
1021
951
|
##
|
1022
952
|
|
1023
|
-
def updateTheme(self):
|
1024
|
-
"""Update theme elements.
|
1025
|
-
"""
|
953
|
+
def updateTheme(self) -> None:
|
954
|
+
"""Update theme elements."""
|
1026
955
|
# Icons
|
1027
|
-
|
1028
956
|
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
957
|
+
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx))
|
1029
958
|
|
1030
|
-
|
1031
|
-
stickyOff = SHARED.theme.getPixmap("sticky-off", (fPx, fPx))
|
1032
|
-
stickyIcon = QIcon()
|
1033
|
-
stickyIcon.addPixmap(stickyOn, QIcon.Normal, QIcon.On)
|
1034
|
-
stickyIcon.addPixmap(stickyOff, QIcon.Normal, QIcon.Off)
|
1035
|
-
|
1036
|
-
bulletOn = SHARED.theme.getPixmap("bullet-on", (fPx, fPx))
|
1037
|
-
bulletOff = SHARED.theme.getPixmap("bullet-off", (fPx, fPx))
|
1038
|
-
bulletIcon = QIcon()
|
1039
|
-
bulletIcon.addPixmap(bulletOn, QIcon.Normal, QIcon.On)
|
1040
|
-
bulletIcon.addPixmap(bulletOff, QIcon.Normal, QIcon.Off)
|
1041
|
-
|
1042
|
-
self.showHide.setIcon(SHARED.theme.getIcon("reference"))
|
1043
|
-
self.stickyRefs.setIcon(stickyIcon)
|
959
|
+
self.showHide.setIcon(SHARED.theme.getIcon("panel"))
|
1044
960
|
self.showComments.setIcon(bulletIcon)
|
1045
961
|
self.showSynopsis.setIcon(bulletIcon)
|
1046
962
|
|
1047
963
|
# StyleSheets
|
1048
|
-
|
1049
964
|
buttonStyle = (
|
1050
965
|
"QToolButton {{border: none; background: transparent;}} "
|
1051
966
|
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
|
1052
967
|
).format(*SHARED.theme.colText)
|
1053
968
|
|
1054
969
|
self.showHide.setStyleSheet(buttonStyle)
|
1055
|
-
self.stickyRefs.setStyleSheet(buttonStyle)
|
1056
970
|
self.showComments.setStyleSheet(buttonStyle)
|
1057
971
|
self.showSynopsis.setStyleSheet(buttonStyle)
|
1058
972
|
|
@@ -1060,138 +974,35 @@ class GuiDocViewFooter(QWidget):
|
|
1060
974
|
|
1061
975
|
return
|
1062
976
|
|
1063
|
-
def matchColours(self):
|
977
|
+
def matchColours(self) -> None:
|
1064
978
|
"""Update the colours of the widget to match those of the syntax
|
1065
979
|
theme rather than the main GUI.
|
1066
980
|
"""
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
self.setPalette(
|
1073
|
-
self.
|
1074
|
-
self.lblSticky.setPalette(thePalette)
|
1075
|
-
self.lblComments.setPalette(thePalette)
|
1076
|
-
self.lblSynopsis.setPalette(thePalette)
|
1077
|
-
|
981
|
+
palette = QPalette()
|
982
|
+
palette.setColor(QPalette.ColorRole.Window, QColor(*SHARED.theme.colBack))
|
983
|
+
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
984
|
+
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
985
|
+
self.setPalette(palette)
|
986
|
+
self.lblComments.setPalette(palette)
|
987
|
+
self.lblSynopsis.setPalette(palette)
|
1078
988
|
return
|
1079
989
|
|
1080
990
|
##
|
1081
|
-
# Slots
|
991
|
+
# Private Slots
|
1082
992
|
##
|
1083
993
|
|
1084
|
-
@pyqtSlot()
|
1085
|
-
def _doShowHide(self):
|
1086
|
-
"""Toggle the expand/collapse of the panel.
|
1087
|
-
"""
|
1088
|
-
isVisible = self.viewMeta.isVisible()
|
1089
|
-
self.viewMeta.setVisible(not isVisible)
|
1090
|
-
return
|
1091
|
-
|
1092
994
|
@pyqtSlot(bool)
|
1093
|
-
def
|
1094
|
-
"""Toggle the
|
1095
|
-
|
1096
|
-
logger.debug("Reference sticky is %s", str(theState))
|
1097
|
-
self.docViewer.stickyRef = theState
|
1098
|
-
if not theState and self.docViewer.docHandle is not None:
|
1099
|
-
self.viewMeta.refreshReferences(self.docViewer.docHandle)
|
1100
|
-
return
|
1101
|
-
|
1102
|
-
@pyqtSlot(bool)
|
1103
|
-
def _doToggleComments(self, theState):
|
1104
|
-
"""Toggle the view comment button and reload the document.
|
1105
|
-
"""
|
1106
|
-
CONFIG.viewComments = theState
|
995
|
+
def _doToggleComments(self, state: bool) -> None:
|
996
|
+
"""Toggle the view comment button and reload the document."""
|
997
|
+
CONFIG.viewComments = state
|
1107
998
|
self.docViewer.reloadText()
|
1108
999
|
return
|
1109
1000
|
|
1110
1001
|
@pyqtSlot(bool)
|
1111
|
-
def _doToggleSynopsis(self,
|
1112
|
-
"""Toggle the view synopsis button and reload the document.
|
1113
|
-
|
1114
|
-
CONFIG.viewSynopsis = theState
|
1002
|
+
def _doToggleSynopsis(self, state: bool) -> None:
|
1003
|
+
"""Toggle the view synopsis button and reload the document."""
|
1004
|
+
CONFIG.viewSynopsis = state
|
1115
1005
|
self.docViewer.reloadText()
|
1116
1006
|
return
|
1117
1007
|
|
1118
1008
|
# END Class GuiDocViewFooter
|
1119
|
-
|
1120
|
-
|
1121
|
-
# =============================================================================================== #
|
1122
|
-
# The Document Back-Reference Panel
|
1123
|
-
# Placed in a separate QSplitter position in the main GUI window
|
1124
|
-
# =============================================================================================== #
|
1125
|
-
|
1126
|
-
class GuiDocViewDetails(QScrollArea):
|
1127
|
-
|
1128
|
-
def __init__(self, mainGui):
|
1129
|
-
super().__init__(parent=mainGui)
|
1130
|
-
|
1131
|
-
logger.debug("Create: GuiDocViewDetails")
|
1132
|
-
|
1133
|
-
self.mainGui = mainGui
|
1134
|
-
|
1135
|
-
self.refList = QLabel("")
|
1136
|
-
self.refList.setWordWrap(True)
|
1137
|
-
self.refList.setAlignment(Qt.AlignTop)
|
1138
|
-
self.refList.setScaledContents(True)
|
1139
|
-
self.refList.linkActivated.connect(self._linkClicked)
|
1140
|
-
|
1141
|
-
self.linkStyle = "style='color: rgb({0},{1},{2})'".format(*SHARED.theme.colLink)
|
1142
|
-
|
1143
|
-
# Assemble
|
1144
|
-
self.outerWidget = QWidget()
|
1145
|
-
self.outerBox = QHBoxLayout()
|
1146
|
-
self.outerBox.addWidget(self.refList, 1)
|
1147
|
-
|
1148
|
-
self.outerWidget.setLayout(self.outerBox)
|
1149
|
-
self.setWidget(self.outerWidget)
|
1150
|
-
|
1151
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
1152
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
1153
|
-
self.setWidgetResizable(True)
|
1154
|
-
self.setMinimumHeight(CONFIG.pxInt(50))
|
1155
|
-
self.setFrameStyle(QFrame.NoFrame)
|
1156
|
-
|
1157
|
-
logger.debug("Ready: GuiDocViewDetails")
|
1158
|
-
|
1159
|
-
return
|
1160
|
-
|
1161
|
-
def refreshReferences(self, tHandle):
|
1162
|
-
"""Update the current list of document references from the
|
1163
|
-
project index.
|
1164
|
-
"""
|
1165
|
-
if self.mainGui.docViewer.stickyRef:
|
1166
|
-
return
|
1167
|
-
|
1168
|
-
theRefs = SHARED.project.index.getBackReferenceList(tHandle)
|
1169
|
-
theList = []
|
1170
|
-
for tHandle in theRefs:
|
1171
|
-
tItem = SHARED.project.tree[tHandle]
|
1172
|
-
if tItem is not None:
|
1173
|
-
theList.append("<a href='%s#%s' %s>%s</a>" % (
|
1174
|
-
tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
|
1175
|
-
))
|
1176
|
-
|
1177
|
-
self.refList.setText(", ".join(theList))
|
1178
|
-
|
1179
|
-
return
|
1180
|
-
|
1181
|
-
##
|
1182
|
-
# Private Slots
|
1183
|
-
##
|
1184
|
-
|
1185
|
-
@pyqtSlot(str)
|
1186
|
-
def _linkClicked(self, theLink):
|
1187
|
-
"""Capture the link-click and forward it to the document viewer
|
1188
|
-
class for handling.
|
1189
|
-
"""
|
1190
|
-
logger.debug("Clicked link: '%s'", theLink)
|
1191
|
-
if len(theLink) >= 13:
|
1192
|
-
tHandle = theLink[:13]
|
1193
|
-
tAnchor = theLink[13:] or None
|
1194
|
-
self.mainGui.viewDocument(tHandle, tAnchor)
|
1195
|
-
return
|
1196
|
-
|
1197
|
-
# END Class GuiDocViewDetails
|