novelWriter 2.5.3__py3-none-any.whl → 2.6b2__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 (83) hide show
  1. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/METADATA +1 -1
  2. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/RECORD +80 -60
  3. novelwriter/__init__.py +49 -10
  4. novelwriter/assets/i18n/project_en_GB.json +1 -0
  5. novelwriter/assets/icons/typicons_dark/icons.conf +8 -0
  6. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
  7. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
  8. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
  9. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
  10. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
  11. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
  12. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
  13. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
  14. novelwriter/assets/icons/typicons_light/icons.conf +8 -0
  15. novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
  16. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
  17. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
  18. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
  19. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
  20. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
  21. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
  22. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
  23. novelwriter/assets/manual.pdf +0 -0
  24. novelwriter/assets/sample.zip +0 -0
  25. novelwriter/common.py +100 -2
  26. novelwriter/config.py +25 -15
  27. novelwriter/constants.py +168 -60
  28. novelwriter/core/buildsettings.py +66 -39
  29. novelwriter/core/coretools.py +145 -147
  30. novelwriter/core/docbuild.py +132 -170
  31. novelwriter/core/index.py +38 -37
  32. novelwriter/core/item.py +41 -8
  33. novelwriter/core/itemmodel.py +518 -0
  34. novelwriter/core/options.py +4 -1
  35. novelwriter/core/project.py +67 -89
  36. novelwriter/core/spellcheck.py +9 -14
  37. novelwriter/core/status.py +7 -5
  38. novelwriter/core/tree.py +268 -287
  39. novelwriter/dialogs/docmerge.py +7 -17
  40. novelwriter/dialogs/preferences.py +46 -33
  41. novelwriter/dialogs/projectsettings.py +5 -5
  42. novelwriter/enum.py +36 -23
  43. novelwriter/extensions/configlayout.py +27 -12
  44. novelwriter/extensions/modified.py +13 -1
  45. novelwriter/extensions/pagedsidebar.py +5 -5
  46. novelwriter/formats/shared.py +155 -0
  47. novelwriter/formats/todocx.py +1191 -0
  48. novelwriter/formats/tohtml.py +451 -0
  49. novelwriter/{core → formats}/tokenizer.py +487 -491
  50. novelwriter/formats/tomarkdown.py +217 -0
  51. novelwriter/{core → formats}/toodt.py +311 -432
  52. novelwriter/formats/toqdoc.py +484 -0
  53. novelwriter/formats/toraw.py +91 -0
  54. novelwriter/gui/doceditor.py +342 -284
  55. novelwriter/gui/dochighlight.py +96 -84
  56. novelwriter/gui/docviewer.py +88 -31
  57. novelwriter/gui/docviewerpanel.py +17 -25
  58. novelwriter/gui/editordocument.py +17 -2
  59. novelwriter/gui/itemdetails.py +25 -28
  60. novelwriter/gui/mainmenu.py +129 -63
  61. novelwriter/gui/noveltree.py +45 -47
  62. novelwriter/gui/outline.py +196 -249
  63. novelwriter/gui/projtree.py +594 -1241
  64. novelwriter/gui/search.py +9 -10
  65. novelwriter/gui/sidebar.py +7 -6
  66. novelwriter/gui/theme.py +10 -5
  67. novelwriter/guimain.py +100 -196
  68. novelwriter/shared.py +66 -27
  69. novelwriter/text/counting.py +2 -0
  70. novelwriter/text/patterns.py +168 -60
  71. novelwriter/tools/manusbuild.py +14 -12
  72. novelwriter/tools/manuscript.py +120 -78
  73. novelwriter/tools/manussettings.py +424 -291
  74. novelwriter/tools/welcome.py +4 -4
  75. novelwriter/tools/writingstats.py +3 -3
  76. novelwriter/types.py +23 -7
  77. novelwriter/core/tohtml.py +0 -530
  78. novelwriter/core/tomarkdown.py +0 -252
  79. novelwriter/core/toqdoc.py +0 -419
  80. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
  81. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +0 -0
  82. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
  83. {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
@@ -28,13 +28,15 @@ import logging
28
28
  from pathlib import Path
29
29
  from typing import TYPE_CHECKING
30
30
 
31
- from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
32
- from PyQt5.QtGui import QDesktopServices
31
+ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
33
32
  from PyQt5.QtWidgets import QAction, QMenuBar
34
33
 
35
34
  from novelwriter import CONFIG, SHARED
36
- from novelwriter.common import openExternalPath
37
- from novelwriter.constants import nwConst, nwKeyWords, nwLabels, nwUnicode, trConst
35
+ from novelwriter.common import openExternalPath, qtLambda
36
+ from novelwriter.constants import (
37
+ nwConst, nwKeyWords, nwLabels, nwShortcode, nwStats, nwStyles, nwUnicode,
38
+ trConst
39
+ )
38
40
  from novelwriter.enum import nwDocAction, nwDocInsert, nwFocus, nwView
39
41
  from novelwriter.extensions.eventfilters import StatusTipFilter
40
42
 
@@ -104,12 +106,6 @@ class GuiMainMenu(QMenuBar):
104
106
  self.mainGui.docEditor.toggleSpellCheck(None)
105
107
  return
106
108
 
107
- @pyqtSlot(str)
108
- def _openWebsite(self, url: str) -> None:
109
- """Open a URL in the system's default browser."""
110
- QDesktopServices.openUrl(QUrl(url))
111
- return
112
-
113
109
  @pyqtSlot()
114
110
  def _openUserManualFile(self) -> None:
115
111
  """Open the documentation in PDF format."""
@@ -141,12 +137,13 @@ class GuiMainMenu(QMenuBar):
141
137
  # Project > Save Project
142
138
  self.aSaveProject = self.projMenu.addAction(self.tr("Save Project"))
143
139
  self.aSaveProject.setShortcut("Ctrl+Shift+S")
144
- self.aSaveProject.triggered.connect(lambda: self.mainGui.saveProject())
140
+ self.aSaveProject.triggered.connect(qtLambda(self.mainGui.saveProject))
141
+ self.mainGui.addAction(self.aSaveProject)
145
142
 
146
143
  # Project > Close Project
147
144
  self.aCloseProject = self.projMenu.addAction(self.tr("Close Project"))
148
145
  self.aCloseProject.setShortcut("Ctrl+Shift+W")
149
- self.aCloseProject.triggered.connect(lambda: self.mainGui.closeProject(False))
146
+ self.aCloseProject.triggered.connect(qtLambda(self.mainGui.closeProject, False))
150
147
 
151
148
  # Project > Separator
152
149
  self.projMenu.addSeparator()
@@ -165,18 +162,20 @@ class GuiMainMenu(QMenuBar):
165
162
  self.projMenu.addSeparator()
166
163
 
167
164
  # Project > Edit
168
- self.aEditItem = self.projMenu.addAction(self.tr("Rename Item"))
169
- self.aEditItem.setShortcut("F2")
170
- self.aEditItem.triggered.connect(lambda: self.mainGui.projView.renameTreeItem(None))
165
+ self.aRenameItem = self.projMenu.addAction(self.tr("Rename Item"))
166
+ self.aRenameItem.setShortcut("F2")
171
167
 
172
168
  # Project > Delete
173
169
  self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
174
- self.aDeleteItem.setShortcut("Ctrl+Shift+Del") # Cannot be Ctrl+Del, see #629
175
- self.aDeleteItem.triggered.connect(lambda: self.mainGui.projView.requestDeleteItem(None))
170
+ self.aDeleteItem.setShortcut("Del")
171
+ self.aDeleteItem.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
176
172
 
177
173
  # Project > Empty Trash
178
174
  self.aEmptyTrash = self.projMenu.addAction(self.tr("Empty Trash"))
179
- self.aEmptyTrash.triggered.connect(lambda: self.mainGui.projView.emptyTrash())
175
+
176
+ self.mainGui.projView.connectMenuActions(
177
+ self.aRenameItem, self.aDeleteItem, self.aEmptyTrash
178
+ )
180
179
 
181
180
  # Project > Separator
182
181
  self.projMenu.addSeparator()
@@ -184,8 +183,9 @@ class GuiMainMenu(QMenuBar):
184
183
  # Project > Exit
185
184
  self.aExitNW = self.projMenu.addAction(self.tr("Exit"))
186
185
  self.aExitNW.setShortcut("Ctrl+Q")
187
- self.aExitNW.setMenuRole(QAction.QuitRole)
188
- self.aExitNW.triggered.connect(lambda: self.mainGui.closeMain())
186
+ self.aExitNW.setMenuRole(QAction.MenuRole.QuitRole)
187
+ self.aExitNW.triggered.connect(qtLambda(self.mainGui.closeMain))
188
+ self.mainGui.addAction(self.aExitNW)
189
189
 
190
190
  return
191
191
 
@@ -203,11 +203,13 @@ class GuiMainMenu(QMenuBar):
203
203
  self.aSaveDoc = self.docuMenu.addAction(self.tr("Save Document"))
204
204
  self.aSaveDoc.setShortcut("Ctrl+S")
205
205
  self.aSaveDoc.triggered.connect(self.mainGui.forceSaveDocument)
206
+ self.mainGui.addAction(self.aSaveDoc)
206
207
 
207
208
  # Document > Close
208
209
  self.aCloseDoc = self.docuMenu.addAction(self.tr("Close Document"))
209
210
  self.aCloseDoc.setShortcut("Ctrl+W")
210
211
  self.aCloseDoc.triggered.connect(self.mainGui.closeDocEditor)
212
+ self.mainGui.addAction(self.aCloseDoc)
211
213
 
212
214
  # Document > Separator
213
215
  self.docuMenu.addSeparator()
@@ -215,7 +217,7 @@ class GuiMainMenu(QMenuBar):
215
217
  # Document > Preview
216
218
  self.aViewDoc = self.docuMenu.addAction(self.tr("View Document"))
217
219
  self.aViewDoc.setShortcut("Ctrl+R")
218
- self.aViewDoc.triggered.connect(lambda: self.mainGui.viewDocument(None))
220
+ self.aViewDoc.triggered.connect(qtLambda(self.mainGui.viewDocument, None))
219
221
 
220
222
  # Document > Close Preview
221
223
  self.aCloseView = self.docuMenu.addAction(self.tr("Close Document View"))
@@ -227,11 +229,11 @@ class GuiMainMenu(QMenuBar):
227
229
 
228
230
  # Document > Show File Details
229
231
  self.aFileDetails = self.docuMenu.addAction(self.tr("Show File Details"))
230
- self.aFileDetails.triggered.connect(lambda: self.mainGui.docEditor.revealLocation())
232
+ self.aFileDetails.triggered.connect(qtLambda(self.mainGui.docEditor.revealLocation))
231
233
 
232
234
  # Document > Import From File
233
235
  self.aImportFile = self.docuMenu.addAction(self.tr("Import Text from File"))
234
- self.aImportFile.triggered.connect(lambda: self.mainGui.importDocument())
236
+ self.aImportFile.triggered.connect(qtLambda(self.mainGui.importDocument))
235
237
 
236
238
  return
237
239
 
@@ -246,6 +248,7 @@ class GuiMainMenu(QMenuBar):
246
248
  self.aEditUndo.triggered.connect(
247
249
  lambda: self.requestDocAction.emit(nwDocAction.UNDO)
248
250
  )
251
+ self.mainGui.addAction(self.aEditUndo)
249
252
 
250
253
  # Edit > Redo
251
254
  self.aEditRedo = self.editMenu.addAction(self.tr("Redo"))
@@ -253,6 +256,7 @@ class GuiMainMenu(QMenuBar):
253
256
  self.aEditRedo.triggered.connect(
254
257
  lambda: self.requestDocAction.emit(nwDocAction.REDO)
255
258
  )
259
+ self.mainGui.addAction(self.aEditRedo)
256
260
 
257
261
  # Edit > Separator
258
262
  self.editMenu.addSeparator()
@@ -263,6 +267,7 @@ class GuiMainMenu(QMenuBar):
263
267
  self.aEditCut.triggered.connect(
264
268
  lambda: self.requestDocAction.emit(nwDocAction.CUT)
265
269
  )
270
+ self.mainGui.addAction(self.aEditCut)
266
271
 
267
272
  # Edit > Copy
268
273
  self.aEditCopy = self.editMenu.addAction(self.tr("Copy"))
@@ -270,6 +275,7 @@ class GuiMainMenu(QMenuBar):
270
275
  self.aEditCopy.triggered.connect(
271
276
  lambda: self.requestDocAction.emit(nwDocAction.COPY)
272
277
  )
278
+ self.mainGui.addAction(self.aEditCopy)
273
279
 
274
280
  # Edit > Paste
275
281
  self.aEditPaste = self.editMenu.addAction(self.tr("Paste"))
@@ -277,6 +283,7 @@ class GuiMainMenu(QMenuBar):
277
283
  self.aEditPaste.triggered.connect(
278
284
  lambda: self.requestDocAction.emit(nwDocAction.PASTE)
279
285
  )
286
+ self.mainGui.addAction(self.aEditPaste)
280
287
 
281
288
  # Edit > Separator
282
289
  self.editMenu.addSeparator()
@@ -287,6 +294,7 @@ class GuiMainMenu(QMenuBar):
287
294
  self.aSelectAll.triggered.connect(
288
295
  lambda: self.requestDocAction.emit(nwDocAction.SEL_ALL)
289
296
  )
297
+ self.mainGui.addAction(self.aSelectAll)
290
298
 
291
299
  # Edit > Select Paragraph
292
300
  self.aSelectPar = self.editMenu.addAction(self.tr("Select Paragraph"))
@@ -294,6 +302,7 @@ class GuiMainMenu(QMenuBar):
294
302
  self.aSelectPar.triggered.connect(
295
303
  lambda: self.requestDocAction.emit(nwDocAction.SEL_PARA)
296
304
  )
305
+ self.mainGui.addAction(self.aSelectPar)
297
306
 
298
307
  return
299
308
 
@@ -329,12 +338,16 @@ class GuiMainMenu(QMenuBar):
329
338
  # View > Go Backward
330
339
  self.aViewPrev = self.viewMenu.addAction(self.tr("Navigate Backward"))
331
340
  self.aViewPrev.setShortcut("Alt+Left")
341
+ self.aViewPrev.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
332
342
  self.aViewPrev.triggered.connect(self.mainGui.docViewer.navBackward)
343
+ self.mainGui.docViewer.addAction(self.aViewPrev)
333
344
 
334
345
  # View > Go Forward
335
346
  self.aViewNext = self.viewMenu.addAction(self.tr("Navigate Forward"))
336
347
  self.aViewNext.setShortcut("Alt+Right")
348
+ self.aViewNext.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
337
349
  self.aViewNext.triggered.connect(self.mainGui.docViewer.navForward)
350
+ self.mainGui.docViewer.addAction(self.aViewNext)
338
351
 
339
352
  # View > Separator
340
353
  self.viewMenu.addSeparator()
@@ -343,11 +356,13 @@ class GuiMainMenu(QMenuBar):
343
356
  self.aFocusMode = self.viewMenu.addAction(self.tr("Focus Mode"))
344
357
  self.aFocusMode.setShortcut("F8")
345
358
  self.aFocusMode.triggered.connect(self.mainGui.toggleFocusMode)
359
+ self.mainGui.addAction(self.aFocusMode)
346
360
 
347
361
  # View > Toggle Full Screen
348
362
  self.aFullScreen = self.viewMenu.addAction(self.tr("Full Screen Mode"))
349
363
  self.aFullScreen.setShortcut("F11")
350
- self.aFullScreen.triggered.connect(lambda: self.mainGui.toggleFullScreenMode())
364
+ self.aFullScreen.triggered.connect(self.mainGui.toggleFullScreenMode)
365
+ self.mainGui.addAction(self.aFullScreen)
351
366
 
352
367
  return
353
368
 
@@ -365,6 +380,7 @@ class GuiMainMenu(QMenuBar):
365
380
  self.aInsENDash.triggered.connect(
366
381
  lambda: self.requestDocInsertText.emit(nwUnicode.U_ENDASH)
367
382
  )
383
+ self.mainGui.addAction(self.aInsENDash)
368
384
 
369
385
  # Insert > Long Dash
370
386
  self.aInsEMDash = self.mInsDashes.addAction(self.tr("Long Dash"))
@@ -372,6 +388,7 @@ class GuiMainMenu(QMenuBar):
372
388
  self.aInsEMDash.triggered.connect(
373
389
  lambda: self.requestDocInsertText.emit(nwUnicode.U_EMDASH)
374
390
  )
391
+ self.mainGui.addAction(self.aInsEMDash)
375
392
 
376
393
  # Insert > Long Dash
377
394
  self.aInsHorBar = self.mInsDashes.addAction(self.tr("Horizontal Bar"))
@@ -379,6 +396,7 @@ class GuiMainMenu(QMenuBar):
379
396
  self.aInsHorBar.triggered.connect(
380
397
  lambda: self.requestDocInsertText.emit(nwUnicode.U_HBAR)
381
398
  )
399
+ self.mainGui.addAction(self.aInsHorBar)
382
400
 
383
401
  # Insert > Figure Dash
384
402
  self.aInsFigDash = self.mInsDashes.addAction(self.tr("Figure Dash"))
@@ -386,6 +404,7 @@ class GuiMainMenu(QMenuBar):
386
404
  self.aInsFigDash.triggered.connect(
387
405
  lambda: self.requestDocInsertText.emit(nwUnicode.U_FGDASH)
388
406
  )
407
+ self.mainGui.addAction(self.aInsFigDash)
389
408
 
390
409
  # Insert > Quote Marks
391
410
  self.mInsQuotes = self.insMenu.addMenu(self.tr("Quote Marks"))
@@ -396,6 +415,7 @@ class GuiMainMenu(QMenuBar):
396
415
  self.aInsQuoteLS.triggered.connect(
397
416
  lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LS)
398
417
  )
418
+ self.mainGui.addAction(self.aInsQuoteLS)
399
419
 
400
420
  # Insert > Right Single Quote
401
421
  self.aInsQuoteRS = self.mInsQuotes.addAction(self.tr("Right Single Quote"))
@@ -403,6 +423,7 @@ class GuiMainMenu(QMenuBar):
403
423
  self.aInsQuoteRS.triggered.connect(
404
424
  lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RS)
405
425
  )
426
+ self.mainGui.addAction(self.aInsQuoteRS)
406
427
 
407
428
  # Insert > Left Double Quote
408
429
  self.aInsQuoteLD = self.mInsQuotes.addAction(self.tr("Left Double Quote"))
@@ -410,6 +431,7 @@ class GuiMainMenu(QMenuBar):
410
431
  self.aInsQuoteLD.triggered.connect(
411
432
  lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_LD)
412
433
  )
434
+ self.mainGui.addAction(self.aInsQuoteLD)
413
435
 
414
436
  # Insert > Right Double Quote
415
437
  self.aInsQuoteRD = self.mInsQuotes.addAction(self.tr("Right Double Quote"))
@@ -417,6 +439,7 @@ class GuiMainMenu(QMenuBar):
417
439
  self.aInsQuoteRD.triggered.connect(
418
440
  lambda: self.requestDocInsert.emit(nwDocInsert.QUOTE_RD)
419
441
  )
442
+ self.mainGui.addAction(self.aInsQuoteRD)
420
443
 
421
444
  # Insert > Alternative Apostrophe
422
445
  self.aInsMSApos = self.mInsQuotes.addAction(self.tr("Alternative Apostrophe"))
@@ -424,6 +447,7 @@ class GuiMainMenu(QMenuBar):
424
447
  self.aInsMSApos.triggered.connect(
425
448
  lambda: self.requestDocInsertText.emit(nwUnicode.U_MAPOS)
426
449
  )
450
+ self.mainGui.addAction(self.aInsMSApos)
427
451
 
428
452
  # Insert > Symbols
429
453
  self.mInsPunct = self.insMenu.addMenu(self.tr("General Punctuation"))
@@ -434,6 +458,7 @@ class GuiMainMenu(QMenuBar):
434
458
  self.aInsEllipsis.triggered.connect(
435
459
  lambda: self.requestDocInsertText.emit(nwUnicode.U_HELLIP)
436
460
  )
461
+ self.mainGui.addAction(self.aInsEllipsis)
437
462
 
438
463
  # Insert > Prime
439
464
  self.aInsPrime = self.mInsPunct.addAction(self.tr("Prime"))
@@ -441,6 +466,7 @@ class GuiMainMenu(QMenuBar):
441
466
  self.aInsPrime.triggered.connect(
442
467
  lambda: self.requestDocInsertText.emit(nwUnicode.U_PRIME)
443
468
  )
469
+ self.mainGui.addAction(self.aInsPrime)
444
470
 
445
471
  # Insert > Double Prime
446
472
  self.aInsDPrime = self.mInsPunct.addAction(self.tr("Double Prime"))
@@ -448,6 +474,7 @@ class GuiMainMenu(QMenuBar):
448
474
  self.aInsDPrime.triggered.connect(
449
475
  lambda: self.requestDocInsertText.emit(nwUnicode.U_DPRIME)
450
476
  )
477
+ self.mainGui.addAction(self.aInsDPrime)
451
478
 
452
479
  # Insert > White Spaces
453
480
  self.mInsSpace = self.insMenu.addMenu(self.tr("White Spaces"))
@@ -458,6 +485,7 @@ class GuiMainMenu(QMenuBar):
458
485
  self.aInsNBSpace.triggered.connect(
459
486
  lambda: self.requestDocInsertText.emit(nwUnicode.U_NBSP)
460
487
  )
488
+ self.mainGui.addAction(self.aInsNBSpace)
461
489
 
462
490
  # Insert > Thin Space
463
491
  self.aInsThinSpace = self.mInsSpace.addAction(self.tr("Thin Space"))
@@ -465,6 +493,7 @@ class GuiMainMenu(QMenuBar):
465
493
  self.aInsThinSpace.triggered.connect(
466
494
  lambda: self.requestDocInsertText.emit(nwUnicode.U_THSP)
467
495
  )
496
+ self.mainGui.addAction(self.aInsThinSpace)
468
497
 
469
498
  # Insert > Thin Non-Breaking Space
470
499
  self.aInsThinNBSpace = self.mInsSpace.addAction(self.tr("Thin Non-Breaking Space"))
@@ -472,6 +501,7 @@ class GuiMainMenu(QMenuBar):
472
501
  self.aInsThinNBSpace.triggered.connect(
473
502
  lambda: self.requestDocInsertText.emit(nwUnicode.U_THNBSP)
474
503
  )
504
+ self.mainGui.addAction(self.aInsThinNBSpace)
475
505
 
476
506
  # Insert > Symbols
477
507
  self.mInsSymbol = self.insMenu.addMenu(self.tr("Other Symbols"))
@@ -482,6 +512,7 @@ class GuiMainMenu(QMenuBar):
482
512
  self.aInsBullet.triggered.connect(
483
513
  lambda: self.requestDocInsertText.emit(nwUnicode.U_BULL)
484
514
  )
515
+ self.mainGui.addAction(self.aInsBullet)
485
516
 
486
517
  # Insert > Hyphen Bullet
487
518
  self.aInsHyBull = self.mInsSymbol.addAction(self.tr("Hyphen Bullet"))
@@ -489,6 +520,7 @@ class GuiMainMenu(QMenuBar):
489
520
  self.aInsHyBull.triggered.connect(
490
521
  lambda: self.requestDocInsertText.emit(nwUnicode.U_HYBULL)
491
522
  )
523
+ self.mainGui.addAction(self.aInsHyBull)
492
524
 
493
525
  # Insert > Flower Mark
494
526
  self.aInsFlower = self.mInsSymbol.addAction(self.tr("Flower Mark"))
@@ -496,6 +528,7 @@ class GuiMainMenu(QMenuBar):
496
528
  self.aInsFlower.triggered.connect(
497
529
  lambda: self.requestDocInsertText.emit(nwUnicode.U_FLOWER)
498
530
  )
531
+ self.mainGui.addAction(self.aInsFlower)
499
532
 
500
533
  # Insert > Per Mille
501
534
  self.aInsPerMille = self.mInsSymbol.addAction(self.tr("Per Mille"))
@@ -503,6 +536,7 @@ class GuiMainMenu(QMenuBar):
503
536
  self.aInsPerMille.triggered.connect(
504
537
  lambda: self.requestDocInsertText.emit(nwUnicode.U_PERMIL)
505
538
  )
539
+ self.mainGui.addAction(self.aInsPerMille)
506
540
 
507
541
  # Insert > Degree Symbol
508
542
  self.aInsDegree = self.mInsSymbol.addAction(self.tr("Degree Symbol"))
@@ -510,6 +544,7 @@ class GuiMainMenu(QMenuBar):
510
544
  self.aInsDegree.triggered.connect(
511
545
  lambda: self.requestDocInsertText.emit(nwUnicode.U_DEGREE)
512
546
  )
547
+ self.mainGui.addAction(self.aInsDegree)
513
548
 
514
549
  # Insert > Minus Sign
515
550
  self.aInsMinus = self.mInsSymbol.addAction(self.tr("Minus Sign"))
@@ -517,6 +552,7 @@ class GuiMainMenu(QMenuBar):
517
552
  self.aInsMinus.triggered.connect(
518
553
  lambda: self.requestDocInsertText.emit(nwUnicode.U_MINUS)
519
554
  )
555
+ self.mainGui.addAction(self.aInsMinus)
520
556
 
521
557
  # Insert > Times Sign
522
558
  self.aInsTimes = self.mInsSymbol.addAction(self.tr("Times Sign"))
@@ -524,6 +560,7 @@ class GuiMainMenu(QMenuBar):
524
560
  self.aInsTimes.triggered.connect(
525
561
  lambda: self.requestDocInsertText.emit(nwUnicode.U_TIMES)
526
562
  )
563
+ self.mainGui.addAction(self.aInsTimes)
527
564
 
528
565
  # Insert > Division
529
566
  self.aInsDivide = self.mInsSymbol.addAction(self.tr("Division Sign"))
@@ -531,27 +568,15 @@ class GuiMainMenu(QMenuBar):
531
568
  self.aInsDivide.triggered.connect(
532
569
  lambda: self.requestDocInsertText.emit(nwUnicode.U_DIVIDE)
533
570
  )
571
+ self.mainGui.addAction(self.aInsDivide)
534
572
 
535
573
  # Insert > Tags and References
536
574
  self.mInsKeywords = self.insMenu.addMenu(self.tr("Tags and References"))
537
- self.mInsKWItems = {}
538
- self.mInsKWItems[nwKeyWords.TAG_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, G")
539
- self.mInsKWItems[nwKeyWords.POV_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, V")
540
- self.mInsKWItems[nwKeyWords.FOCUS_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, F")
541
- self.mInsKWItems[nwKeyWords.CHAR_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, C")
542
- self.mInsKWItems[nwKeyWords.PLOT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, P")
543
- self.mInsKWItems[nwKeyWords.TIME_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, T")
544
- self.mInsKWItems[nwKeyWords.WORLD_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, L")
545
- self.mInsKWItems[nwKeyWords.OBJECT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, O")
546
- self.mInsKWItems[nwKeyWords.ENTITY_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, E")
547
- self.mInsKWItems[nwKeyWords.CUSTOM_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, X")
548
- for n, keyWord in enumerate(self.mInsKWItems):
549
- self.mInsKWItems[keyWord][0].setText(trConst(nwLabels.KEY_NAME[keyWord]))
550
- self.mInsKWItems[keyWord][0].setShortcut(self.mInsKWItems[keyWord][1])
551
- self.mInsKWItems[keyWord][0].triggered.connect(
552
- lambda n, keyWord=keyWord: self.requestDocKeyWordInsert.emit(keyWord)
553
- )
554
- self.mInsKeywords.addAction(self.mInsKWItems[keyWord][0])
575
+ for key in nwKeyWords.ALL_KEYS:
576
+ action = self.mInsKeywords.addAction(trConst(nwLabels.KEY_NAME[key]))
577
+ action.setShortcut(nwLabels.KEY_SHORTCUT[key])
578
+ action.triggered.connect(qtLambda(self.requestDocKeyWordInsert.emit, key))
579
+ self.mainGui.addAction(action)
555
580
 
556
581
  # Insert > Special Comments
557
582
  self.mInsComments = self.insMenu.addMenu(self.tr("Special Comments"))
@@ -562,6 +587,7 @@ class GuiMainMenu(QMenuBar):
562
587
  self.aInsSynopsis.triggered.connect(
563
588
  lambda: self.requestDocInsert.emit(nwDocInsert.SYNOPSIS)
564
589
  )
590
+ self.mainGui.addAction(self.aInsSynopsis)
565
591
 
566
592
  # Insert > Short Description Comment
567
593
  self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment"))
@@ -569,9 +595,17 @@ class GuiMainMenu(QMenuBar):
569
595
  self.aInsShort.triggered.connect(
570
596
  lambda: self.requestDocInsert.emit(nwDocInsert.SHORT)
571
597
  )
598
+ self.mainGui.addAction(self.aInsShort)
572
599
 
573
- # Insert > Symbols
574
- self.mInsBreaks = self.insMenu.addMenu(self.tr("Page Break and Space"))
600
+ # Insert > Word/Character Count
601
+ self.mInsField = self.insMenu.addMenu(self.tr("Word/Character Count"))
602
+ for field in nwStats.ALL_FIELDS:
603
+ value = nwShortcode.FIELD_VALUE.format(field)
604
+ action = self.mInsField.addAction(trConst(nwLabels.STATS_NAME[field]))
605
+ action.triggered.connect(qtLambda(self.requestDocInsertText.emit, value))
606
+
607
+ # Insert > Breaks and Vertical Space
608
+ self.mInsBreaks = self.insMenu.addMenu(self.tr("Breaks and Vertical Space"))
575
609
 
576
610
  # Insert > New Page
577
611
  self.aInsNewPage = self.mInsBreaks.addAction(self.tr("Page Break"))
@@ -579,6 +613,12 @@ class GuiMainMenu(QMenuBar):
579
613
  lambda: self.requestDocInsert.emit(nwDocInsert.NEW_PAGE)
580
614
  )
581
615
 
616
+ # Insert > Forced Line Break
617
+ self.aInsLineBreak = self.mInsBreaks.addAction(self.tr("Forced Line Break"))
618
+ self.aInsLineBreak.triggered.connect(
619
+ lambda: self.requestDocInsert.emit(nwDocInsert.LINE_BRK)
620
+ )
621
+
582
622
  # Insert > Vertical Space (Single)
583
623
  self.aInsVSpaceS = self.mInsBreaks.addAction(self.tr("Vertical Space (Single)"))
584
624
  self.aInsVSpaceS.triggered.connect(
@@ -616,6 +656,7 @@ class GuiMainMenu(QMenuBar):
616
656
  self.aFmtBold.triggered.connect(
617
657
  lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
618
658
  )
659
+ self.mainGui.addAction(self.aFmtBold)
619
660
 
620
661
  # Format > Italic
621
662
  self.aFmtItalic = self.fmtMenu.addAction(self.tr("Italic"))
@@ -623,6 +664,7 @@ class GuiMainMenu(QMenuBar):
623
664
  self.aFmtItalic.triggered.connect(
624
665
  lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
625
666
  )
667
+ self.mainGui.addAction(self.aFmtItalic)
626
668
 
627
669
  # Format > Strikethrough
628
670
  self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough"))
@@ -630,6 +672,7 @@ class GuiMainMenu(QMenuBar):
630
672
  self.aFmtStrike.triggered.connect(
631
673
  lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
632
674
  )
675
+ self.mainGui.addAction(self.aFmtStrike)
633
676
 
634
677
  # Edit > Separator
635
678
  self.fmtMenu.addSeparator()
@@ -640,6 +683,7 @@ class GuiMainMenu(QMenuBar):
640
683
  self.aFmtDQuote.triggered.connect(
641
684
  lambda: self.requestDocAction.emit(nwDocAction.D_QUOTE)
642
685
  )
686
+ self.mainGui.addAction(self.aFmtDQuote)
643
687
 
644
688
  # Format > Single Quotes
645
689
  self.aFmtSQuote = self.fmtMenu.addAction(self.tr("Wrap Single Quotes"))
@@ -647,6 +691,7 @@ class GuiMainMenu(QMenuBar):
647
691
  self.aFmtSQuote.triggered.connect(
648
692
  lambda: self.requestDocAction.emit(nwDocAction.S_QUOTE)
649
693
  )
694
+ self.mainGui.addAction(self.aFmtSQuote)
650
695
 
651
696
  # Format > Separator
652
697
  self.fmtMenu.addSeparator()
@@ -700,32 +745,36 @@ class GuiMainMenu(QMenuBar):
700
745
  self.fmtMenu.addSeparator()
701
746
 
702
747
  # Format > Heading 1 (Partition)
703
- self.aFmtHead1 = self.fmtMenu.addAction(self.tr("Heading 1 (Partition)"))
748
+ self.aFmtHead1 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H1"]))
704
749
  self.aFmtHead1.setShortcut("Ctrl+1")
705
750
  self.aFmtHead1.triggered.connect(
706
751
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H1)
707
752
  )
753
+ self.mainGui.addAction(self.aFmtHead1)
708
754
 
709
755
  # Format > Heading 2 (Chapter)
710
- self.aFmtHead2 = self.fmtMenu.addAction(self.tr("Heading 2 (Chapter)"))
756
+ self.aFmtHead2 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H2"]))
711
757
  self.aFmtHead2.setShortcut("Ctrl+2")
712
758
  self.aFmtHead2.triggered.connect(
713
759
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H2)
714
760
  )
761
+ self.mainGui.addAction(self.aFmtHead2)
715
762
 
716
763
  # Format > Heading 3 (Scene)
717
- self.aFmtHead3 = self.fmtMenu.addAction(self.tr("Heading 3 (Scene)"))
764
+ self.aFmtHead3 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H3"]))
718
765
  self.aFmtHead3.setShortcut("Ctrl+3")
719
766
  self.aFmtHead3.triggered.connect(
720
767
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H3)
721
768
  )
769
+ self.mainGui.addAction(self.aFmtHead3)
722
770
 
723
771
  # Format > Heading 4 (Section)
724
- self.aFmtHead4 = self.fmtMenu.addAction(self.tr("Heading 4 (Section)"))
772
+ self.aFmtHead4 = self.fmtMenu.addAction(trConst(nwStyles.T_LABEL["H4"]))
725
773
  self.aFmtHead4.setShortcut("Ctrl+4")
726
774
  self.aFmtHead4.triggered.connect(
727
775
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_H4)
728
776
  )
777
+ self.mainGui.addAction(self.aFmtHead4)
729
778
 
730
779
  # Format > Separator
731
780
  self.fmtMenu.addSeparator()
@@ -757,6 +806,7 @@ class GuiMainMenu(QMenuBar):
757
806
  self.aFmtAlignLeft.triggered.connect(
758
807
  lambda: self.requestDocAction.emit(nwDocAction.ALIGN_L)
759
808
  )
809
+ self.mainGui.addAction(self.aFmtAlignLeft)
760
810
 
761
811
  # Format > Align Centre
762
812
  self.aFmtAlignCentre = self.fmtMenu.addAction(self.tr("Align Centre"))
@@ -764,6 +814,7 @@ class GuiMainMenu(QMenuBar):
764
814
  self.aFmtAlignCentre.triggered.connect(
765
815
  lambda: self.requestDocAction.emit(nwDocAction.ALIGN_C)
766
816
  )
817
+ self.mainGui.addAction(self.aFmtAlignCentre)
767
818
 
768
819
  # Format > Align Right
769
820
  self.aFmtAlignRight = self.fmtMenu.addAction(self.tr("Align Right"))
@@ -771,6 +822,7 @@ class GuiMainMenu(QMenuBar):
771
822
  self.aFmtAlignRight.triggered.connect(
772
823
  lambda: self.requestDocAction.emit(nwDocAction.ALIGN_R)
773
824
  )
825
+ self.mainGui.addAction(self.aFmtAlignRight)
774
826
 
775
827
  # Format > Separator
776
828
  self.fmtMenu.addSeparator()
@@ -781,6 +833,7 @@ class GuiMainMenu(QMenuBar):
781
833
  self.aFmtIndentLeft.triggered.connect(
782
834
  lambda: self.requestDocAction.emit(nwDocAction.INDENT_L)
783
835
  )
836
+ self.mainGui.addAction(self.aFmtIndentLeft)
784
837
 
785
838
  # Format > Indent Right
786
839
  self.aFmtIndentRight = self.fmtMenu.addAction(self.tr("Indent Right"))
@@ -788,6 +841,7 @@ class GuiMainMenu(QMenuBar):
788
841
  self.aFmtIndentRight.triggered.connect(
789
842
  lambda: self.requestDocAction.emit(nwDocAction.INDENT_R)
790
843
  )
844
+ self.mainGui.addAction(self.aFmtIndentRight)
791
845
 
792
846
  # Format > Separator
793
847
  self.fmtMenu.addSeparator()
@@ -798,6 +852,7 @@ class GuiMainMenu(QMenuBar):
798
852
  self.aFmtComment.triggered.connect(
799
853
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_COM)
800
854
  )
855
+ self.mainGui.addAction(self.aFmtComment)
801
856
 
802
857
  # Format > Ignore Text
803
858
  self.aFmtIgnore = self.fmtMenu.addAction(self.tr("Toggle Ignore Text"))
@@ -812,6 +867,7 @@ class GuiMainMenu(QMenuBar):
812
867
  self.aFmtNoFormat.triggered.connect(
813
868
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_TXT)
814
869
  )
870
+ self.mainGui.addAction(self.aFmtNoFormat)
815
871
 
816
872
  # Format > Separator
817
873
  self.fmtMenu.addSeparator()
@@ -844,29 +900,34 @@ class GuiMainMenu(QMenuBar):
844
900
  # Search > Find
845
901
  self.aFind = self.srcMenu.addAction(self.tr("Find"))
846
902
  self.aFind.setShortcut("Ctrl+F")
847
- self.aFind.triggered.connect(lambda: self.mainGui.docEditor.beginSearch())
903
+ self.aFind.triggered.connect(qtLambda(self.mainGui.docEditor.beginSearch))
904
+ self.mainGui.addAction(self.aFind)
848
905
 
849
906
  # Search > Replace
850
907
  self.aReplace = self.srcMenu.addAction(self.tr("Replace"))
851
908
  self.aReplace.setShortcut("Ctrl+=" if CONFIG.osDarwin else "Ctrl+H")
852
- self.aReplace.triggered.connect(lambda: self.mainGui.docEditor.beginReplace())
909
+ self.aReplace.triggered.connect(qtLambda(self.mainGui.docEditor.beginReplace))
910
+ self.mainGui.addAction(self.aReplace)
853
911
 
854
912
  # Search > Find Next
855
913
  self.aFindNext = self.srcMenu.addAction(self.tr("Find Next"))
856
914
  self.aFindNext.setShortcuts(["Ctrl+G", "F3"] if CONFIG.osDarwin else ["F3", "Ctrl+G"])
857
- self.aFindNext.triggered.connect(lambda: self.mainGui.docEditor.findNext())
915
+ self.aFindNext.triggered.connect(qtLambda(self.mainGui.docEditor.findNext))
916
+ self.mainGui.addAction(self.aFindNext)
858
917
 
859
918
  # Search > Find Prev
860
919
  self.aFindPrev = self.srcMenu.addAction(self.tr("Find Previous"))
861
920
  self.aFindPrev.setShortcuts(
862
921
  ["Ctrl+Shift+G", "Shift+F3"] if CONFIG.osDarwin else ["Shift+F3", "Ctrl+Shift+G"]
863
922
  )
864
- self.aFindPrev.triggered.connect(lambda: self.mainGui.docEditor.findNext(goBack=True))
923
+ self.aFindPrev.triggered.connect(qtLambda(self.mainGui.docEditor.findNext, goBack=True))
924
+ self.mainGui.addAction(self.aFindPrev)
865
925
 
866
926
  # Search > Replace Next
867
927
  self.aReplaceNext = self.srcMenu.addAction(self.tr("Replace Next"))
868
928
  self.aReplaceNext.setShortcut("Ctrl+Shift+1")
869
- self.aReplaceNext.triggered.connect(lambda: self.mainGui.docEditor.replaceNext())
929
+ self.aReplaceNext.triggered.connect(qtLambda(self.mainGui.docEditor.replaceNext))
930
+ self.mainGui.addAction(self.aReplaceNext)
870
931
 
871
932
  # Search > Separator
872
933
  self.srcMenu.addSeparator()
@@ -889,6 +950,7 @@ class GuiMainMenu(QMenuBar):
889
950
  self.aSpellCheck.setChecked(SHARED.project.data.spellCheck)
890
951
  self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled!
891
952
  self.aSpellCheck.setShortcut("Ctrl+F7")
953
+ self.mainGui.addAction(self.aSpellCheck)
892
954
 
893
955
  self.mSelectLanguage = self.toolsMenu.addMenu(self.tr("Spell Check Language"))
894
956
  languages = SHARED.spelling.listDictionaries()
@@ -902,7 +964,8 @@ class GuiMainMenu(QMenuBar):
902
964
  # Tools > Re-Run Spell Check
903
965
  self.aReRunSpell = self.toolsMenu.addAction(self.tr("Re-Run Spell Check"))
904
966
  self.aReRunSpell.setShortcut("F7")
905
- self.aReRunSpell.triggered.connect(lambda: self.mainGui.docEditor.spellCheckDocument())
967
+ self.aReRunSpell.triggered.connect(qtLambda(self.mainGui.docEditor.spellCheckDocument))
968
+ self.mainGui.addAction(self.aReRunSpell)
906
969
 
907
970
  # Tools > Project Word List
908
971
  self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List"))
@@ -919,14 +982,14 @@ class GuiMainMenu(QMenuBar):
919
982
  # Tools > Rebuild Index
920
983
  self.aRebuildIndex = self.toolsMenu.addAction(self.tr("Rebuild Index"))
921
984
  self.aRebuildIndex.setShortcut("F9")
922
- self.aRebuildIndex.triggered.connect(lambda: self.mainGui.rebuildIndex())
985
+ self.aRebuildIndex.triggered.connect(qtLambda(self.mainGui.rebuildIndex))
923
986
 
924
987
  # Tools > Separator
925
988
  self.toolsMenu.addSeparator()
926
989
 
927
990
  # Tools > Backup Project
928
991
  self.aBackupProject = self.toolsMenu.addAction(self.tr("Backup Project"))
929
- self.aBackupProject.triggered.connect(lambda: SHARED.project.backupProject(True))
992
+ self.aBackupProject.triggered.connect(qtLambda(SHARED.project.backupProject, True))
930
993
 
931
994
  # Tools > Build Manuscript
932
995
  self.aBuildManuscript = self.toolsMenu.addAction(self.tr("Build Manuscript"))
@@ -941,8 +1004,9 @@ class GuiMainMenu(QMenuBar):
941
1004
  # Tools > Preferences
942
1005
  self.aPreferences = self.toolsMenu.addAction(self.tr("Preferences"))
943
1006
  self.aPreferences.setShortcut("Ctrl+,")
944
- self.aPreferences.setMenuRole(QAction.PreferencesRole)
1007
+ self.aPreferences.setMenuRole(QAction.MenuRole.PreferencesRole)
945
1008
  self.aPreferences.triggered.connect(self.mainGui.showPreferencesDialog)
1009
+ self.mainGui.addAction(self.aPreferences)
946
1010
 
947
1011
  return
948
1012
 
@@ -953,12 +1017,12 @@ class GuiMainMenu(QMenuBar):
953
1017
 
954
1018
  # Help > About
955
1019
  self.aAboutNW = self.helpMenu.addAction(self.tr("About novelWriter"))
956
- self.aAboutNW.setMenuRole(QAction.AboutRole)
1020
+ self.aAboutNW.setMenuRole(QAction.MenuRole.AboutRole)
957
1021
  self.aAboutNW.triggered.connect(self.mainGui.showAboutNWDialog)
958
1022
 
959
1023
  # Help > About Qt5
960
1024
  self.aAboutQt = self.helpMenu.addAction(self.tr("About Qt5"))
961
- self.aAboutQt.setMenuRole(QAction.AboutQtRole)
1025
+ self.aAboutQt.setMenuRole(QAction.MenuRole.AboutQtRole)
962
1026
  self.aAboutQt.triggered.connect(self.mainGui.showAboutQtDialog)
963
1027
 
964
1028
  # Help > Separator
@@ -967,27 +1031,29 @@ class GuiMainMenu(QMenuBar):
967
1031
  # Help > User Manual (Online)
968
1032
  self.aHelpDocs = self.helpMenu.addAction(self.tr("User Manual (Online)"))
969
1033
  self.aHelpDocs.setShortcut("F1")
970
- self.aHelpDocs.triggered.connect(lambda: self._openWebsite(nwConst.URL_DOCS))
1034
+ self.aHelpDocs.triggered.connect(qtLambda(SHARED.openWebsite, nwConst.URL_DOCS))
1035
+ self.mainGui.addAction(self.aHelpDocs)
971
1036
 
972
1037
  # Help > User Manual (PDF)
973
1038
  if isinstance(CONFIG.pdfDocs, Path):
974
1039
  self.aPdfDocs = self.helpMenu.addAction(self.tr("User Manual (PDF)"))
975
1040
  self.aPdfDocs.setShortcut("Shift+F1")
976
1041
  self.aPdfDocs.triggered.connect(self._openUserManualFile)
1042
+ self.mainGui.addAction(self.aPdfDocs)
977
1043
 
978
1044
  # Help > Separator
979
1045
  self.helpMenu.addSeparator()
980
1046
 
981
1047
  # Document > Report an Issue
982
1048
  self.aIssue = self.helpMenu.addAction(self.tr("Report an Issue (GitHub)"))
983
- self.aIssue.triggered.connect(lambda: self._openWebsite(nwConst.URL_REPORT))
1049
+ self.aIssue.triggered.connect(qtLambda(SHARED.openWebsite, nwConst.URL_REPORT))
984
1050
 
985
1051
  # Document > Ask a Question
986
1052
  self.aQuestion = self.helpMenu.addAction(self.tr("Ask a Question (GitHub)"))
987
- self.aQuestion.triggered.connect(lambda: self._openWebsite(nwConst.URL_HELP))
1053
+ self.aQuestion.triggered.connect(qtLambda(SHARED.openWebsite, nwConst.URL_HELP))
988
1054
 
989
1055
  # Document > Main Website
990
1056
  self.aWebsite = self.helpMenu.addAction(self.tr("The novelWriter Website"))
991
- self.aWebsite.triggered.connect(lambda: self._openWebsite(nwConst.URL_WEB))
1057
+ self.aWebsite.triggered.connect(qtLambda(SHARED.openWebsite, nwConst.URL_WEB))
992
1058
 
993
1059
  return