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.
Files changed (134) hide show
  1. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +3 -3
  2. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +128 -114
  3. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +10 -5
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  9. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  10. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  11. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  12. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  13. novelwriter/assets/i18n/project_de_DE.json +1 -0
  14. novelwriter/assets/i18n/project_en_GB.json +1 -0
  15. novelwriter/assets/i18n/project_en_US.json +1 -0
  16. novelwriter/assets/i18n/project_es_419.json +11 -0
  17. novelwriter/assets/i18n/project_fr_FR.json +11 -0
  18. novelwriter/assets/i18n/project_it_IT.json +11 -0
  19. novelwriter/assets/i18n/project_ja_JP.json +2 -1
  20. novelwriter/assets/i18n/project_nb_NO.json +1 -0
  21. novelwriter/assets/i18n/project_zh_CN.json +11 -0
  22. novelwriter/assets/icons/novelwriter.ico +0 -0
  23. novelwriter/assets/icons/typicons_dark/icons.conf +11 -3
  24. novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +4 -0
  25. novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +4 -0
  26. novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +4 -0
  27. novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +4 -0
  28. novelwriter/assets/icons/typicons_dark/nw_panel.svg +4 -0
  29. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
  30. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
  31. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
  32. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
  33. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
  34. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
  35. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
  36. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
  37. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
  38. novelwriter/assets/icons/typicons_dark/typ_eye.svg +4 -0
  39. novelwriter/assets/icons/typicons_light/icons.conf +11 -3
  40. novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +4 -0
  41. novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +4 -0
  42. novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +4 -0
  43. novelwriter/assets/icons/typicons_light/nw_deco-note.svg +4 -0
  44. novelwriter/assets/icons/typicons_light/nw_panel.svg +4 -0
  45. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
  46. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
  47. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
  48. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
  49. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
  50. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
  51. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
  52. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
  53. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
  54. novelwriter/assets/icons/typicons_light/typ_eye.svg +4 -0
  55. novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
  56. novelwriter/assets/manual.pdf +0 -0
  57. novelwriter/assets/sample.zip +0 -0
  58. novelwriter/assets/text/release_notes.htm +50 -7
  59. novelwriter/common.py +35 -27
  60. novelwriter/config.py +13 -28
  61. novelwriter/constants.py +21 -4
  62. novelwriter/core/buildsettings.py +2 -2
  63. novelwriter/core/coretools.py +8 -2
  64. novelwriter/core/docbuild.py +1 -1
  65. novelwriter/core/document.py +1 -1
  66. novelwriter/core/index.py +102 -36
  67. novelwriter/core/item.py +2 -2
  68. novelwriter/core/options.py +6 -3
  69. novelwriter/core/project.py +5 -5
  70. novelwriter/core/projectdata.py +3 -3
  71. novelwriter/core/projectxml.py +1 -1
  72. novelwriter/core/sessions.py +2 -2
  73. novelwriter/core/spellcheck.py +4 -3
  74. novelwriter/core/status.py +3 -3
  75. novelwriter/core/storage.py +1 -1
  76. novelwriter/core/tohtml.py +11 -5
  77. novelwriter/core/tokenizer.py +28 -21
  78. novelwriter/core/tomd.py +6 -2
  79. novelwriter/core/toodt.py +12 -5
  80. novelwriter/core/tree.py +2 -2
  81. novelwriter/dialogs/about.py +30 -31
  82. novelwriter/dialogs/docmerge.py +24 -15
  83. novelwriter/dialogs/docsplit.py +27 -16
  84. novelwriter/dialogs/editlabel.py +19 -7
  85. novelwriter/dialogs/preferences.py +116 -131
  86. novelwriter/dialogs/projdetails.py +29 -36
  87. novelwriter/dialogs/projload.py +32 -36
  88. novelwriter/dialogs/projsettings.py +20 -15
  89. novelwriter/dialogs/quotes.py +32 -25
  90. novelwriter/dialogs/updates.py +17 -16
  91. novelwriter/dialogs/wordlist.py +34 -21
  92. novelwriter/enum.py +19 -8
  93. novelwriter/error.py +1 -1
  94. novelwriter/extensions/circularprogress.py +1 -1
  95. novelwriter/extensions/configlayout.py +3 -15
  96. novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
  97. novelwriter/extensions/novelselector.py +1 -1
  98. novelwriter/extensions/pageddialog.py +1 -1
  99. novelwriter/extensions/pagedsidebar.py +2 -5
  100. novelwriter/extensions/simpleprogress.py +8 -9
  101. novelwriter/extensions/statusled.py +1 -1
  102. novelwriter/extensions/switch.py +4 -4
  103. novelwriter/extensions/switchbox.py +1 -6
  104. novelwriter/gui/doceditor.py +349 -236
  105. novelwriter/gui/dochighlight.py +10 -11
  106. novelwriter/gui/docviewer.py +158 -360
  107. novelwriter/gui/docviewerpanel.py +502 -0
  108. novelwriter/gui/editordocument.py +4 -4
  109. novelwriter/gui/itemdetails.py +2 -2
  110. novelwriter/gui/mainmenu.py +50 -36
  111. novelwriter/gui/noveltree.py +44 -53
  112. novelwriter/gui/outline.py +12 -7
  113. novelwriter/gui/projtree.py +465 -381
  114. novelwriter/gui/sidebar.py +9 -7
  115. novelwriter/gui/statusbar.py +48 -5
  116. novelwriter/gui/theme.py +26 -8
  117. novelwriter/guimain.py +212 -208
  118. novelwriter/shared.py +76 -30
  119. novelwriter/tools/dictionaries.py +268 -0
  120. novelwriter/tools/lipsum.py +34 -28
  121. novelwriter/tools/manusbuild.py +20 -10
  122. novelwriter/tools/manuscript.py +20 -27
  123. novelwriter/tools/manussettings.py +2 -4
  124. novelwriter/tools/projwizard.py +3 -3
  125. novelwriter/tools/writingstats.py +18 -5
  126. novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
  127. novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
  128. novelwriter/assets/icons/typicons_dark/typ_at.svg +0 -4
  129. novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
  130. novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
  131. novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
  132. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
  133. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
  134. {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
@@ -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–2023, Veronica Berglyd Olsen
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, qApp, QFrame, QHBoxLayout, QLabel, QMenu, QScrollArea,
42
- QTextBrowser, QToolButton, QWidget
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.wheeleventfilter import WheelEventFilter
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
- # Loop through the text and put back in the tabs. Tabs are removed by
230
- # the setHtml function, so the ToHtml class puts in a placeholder.
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
- theCursor = self.textCursor()
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, theAction: nwDocAction) -> bool:
265
+ def docAction(self, action: nwDocAction) -> bool:
267
266
  """Process document actions on the current document."""
268
- logger.debug("Requesting action: '%s'", theAction.name)
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 theAction == nwDocAction.CUT:
271
+ if action == nwDocAction.CUT:
273
272
  self.copy()
274
- elif theAction == nwDocAction.COPY:
273
+ elif action == nwDocAction.COPY:
275
274
  self.copy()
276
- elif theAction == nwDocAction.SEL_ALL:
277
- self._makeSelection(QTextCursor.Document)
278
- elif theAction == nwDocAction.SEL_PARA:
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(theAction))
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) -> bool:
284
+ def navigateTo(self, tAnchor: str) -> None:
286
285
  """Go to a specific #link in the document."""
287
- if not isinstance(tAnchor, str):
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 True
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 titlebar if needed."""
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 internally in the document."""
370
- theLink = url.url()
371
- logger.debug("Clicked link: '%s'", theLink)
372
- if len(theLink) > 0:
373
- theBits = theLink.split("=")
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
- mnuContext = QMenu(self)
385
-
386
- # Cut, Copy and Paste
387
- # ===================
381
+ ctxMenu = QMenu(self)
388
382
 
389
383
  if userSelection:
390
- mnuCopy = QAction(self.tr("Copy"), mnuContext)
384
+ mnuCopy = QAction(self.tr("Copy"), ctxMenu)
391
385
  mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
392
- mnuContext.addAction(mnuCopy)
393
-
394
- mnuContext.addSeparator()
386
+ ctxMenu.addAction(mnuCopy)
395
387
 
396
- # Selections
397
- # ==========
388
+ ctxMenu.addSeparator()
398
389
 
399
- mnuSelAll = QAction(self.tr("Select All"), mnuContext)
390
+ mnuSelAll = QAction(self.tr("Select All"), ctxMenu)
400
391
  mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
401
- mnuContext.addAction(mnuSelAll)
392
+ ctxMenu.addAction(mnuSelAll)
402
393
 
403
- mnuSelWord = QAction(self.tr("Select Word"), mnuContext)
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
- mnuContext.addAction(mnuSelWord)
398
+ ctxMenu.addAction(mnuSelWord)
408
399
 
409
- mnuSelPara = QAction(self.tr("Select Paragraph"), mnuContext)
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
- mnuContext.addAction(mnuSelPara)
404
+ ctxMenu.addAction(mnuSelPara)
414
405
 
415
406
  # Open the context menu
416
- mnuContext.exec_(self.viewport().mapToGlobal(point))
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 select of text based on a selection mode."""
446
- theCursor = self.textCursor()
447
- theCursor.clearSelection()
448
- theCursor.select(selType)
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 = theCursor.selectionStart()
454
- posE = theCursor.selectionEnd()
455
- selTxt = theCursor.selectedText()
445
+ posS = cursor.selectionStart()
446
+ posE = cursor.selectionEnd()
447
+ selTxt = cursor.selectedText()
456
448
  if selTxt.startswith(nwUnicode.U_PSEP):
457
- theCursor.setPosition(posS+1, QTextCursor.MoveAnchor)
458
- theCursor.setPosition(posE, QTextCursor.KeepAnchor)
449
+ cursor.setPosition(posS+1, QTextCursor.MoveMode.MoveAnchor)
450
+ cursor.setPosition(posE, QTextCursor.MoveMode.KeepAnchor)
459
451
 
460
- self.setTextCursor(theCursor)
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
- theCursor = self.cursorForPosition(pos)
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 logger.getEffectiveLevel() == logging.DEBUG:
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.theTitle = QLabel()
689
- self.theTitle.setText("")
690
- self.theTitle.setIndent(0)
691
- self.theTitle.setMargin(0)
692
- self.theTitle.setContentsMargins(0, 0, 0, 0)
693
- self.theTitle.setAutoFillBackground(True)
694
- self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
695
- self.theTitle.setFixedHeight(fPx)
696
-
697
- lblFont = self.theTitle.font()
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.theTitle.setFont(lblFont)
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.theTitle, 1)
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
- thePalette = QPalette()
793
- thePalette.setColor(QPalette.Window, QColor(*SHARED.theme.colBack))
794
- thePalette.setColor(QPalette.WindowText, QColor(*SHARED.theme.colText))
795
- thePalette.setColor(QPalette.Text, QColor(*SHARED.theme.colText))
796
-
797
- self.setPalette(thePalette)
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.theTitle.setText("")
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 True
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.theTitle.setText(sSep.join(tTitle))
795
+ self.docTitle.setText(sSep.join(tTitle))
825
796
  else:
826
- nwItem = pTree[tHandle]
827
- if nwItem is None:
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 True
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, theEvent):
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
- self.mainGui.projView.setSelectedHandle(self._docHandle, doScroll=True)
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
- bSp = CONFIG.pxInt(2)
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.setFixedSize(QSize(fPx, fPx))
911
- self.showHide.clicked.connect(self._doShowHide)
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.ToolButtonIconOnly)
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 comments"))
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.ToolButtonIconOnly)
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 synopsis comments"))
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.lblRefs.setFont(lblFont)
985
- self.lblSticky.setFont(lblFont)
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.addWidget(self.lblSynopsis, 0)
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("reference"))
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
- thePalette = QPalette()
1056
- thePalette.setColor(QPalette.Window, QColor(*SHARED.theme.colBack))
1057
- thePalette.setColor(QPalette.WindowText, QColor(*SHARED.theme.colText))
1058
- thePalette.setColor(QPalette.Text, QColor(*SHARED.theme.colText))
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 _doToggleSticky(self, theState):
1082
- """Toggle the sticky flag for the reference panel.
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, theState):
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