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
@@ -3,10 +3,10 @@ novelWriter – GUI Main Window SideBar
3
3
  =====================================
4
4
 
5
5
  File History:
6
- Created: 2022-05-10 [2.0rc1]
6
+ Created: 2022-05-10 [2.0rc1] GuiSideBar
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2023, Veronica Berglyd Olsen
9
+ Copyright 2018–2024, Veronica Berglyd Olsen
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -27,12 +27,13 @@ import logging
27
27
 
28
28
  from typing import TYPE_CHECKING
29
29
 
30
- from PyQt5.QtCore import QEvent, QPoint, Qt, QSize, pyqtSignal
31
30
  from PyQt5.QtGui import QPalette
31
+ from PyQt5.QtCore import QEvent, QPoint, Qt, QSize, pyqtSignal
32
32
  from PyQt5.QtWidgets import QMenu, QToolButton, QVBoxLayout, QWidget
33
33
 
34
34
  from novelwriter import CONFIG, SHARED
35
35
  from novelwriter.enum import nwView
36
+ from novelwriter.extensions.eventfilters import StatusTipFilter
36
37
 
37
38
  if TYPE_CHECKING: # pragma: no cover
38
39
  from novelwriter.guimain import GuiMain
@@ -54,6 +55,7 @@ class GuiSideBar(QWidget):
54
55
  iPx = CONFIG.pxInt(24)
55
56
  iconSize = QSize(iPx, iPx)
56
57
  self.setContentsMargins(0, 0, 0, 0)
58
+ self.installEventFilter(StatusTipFilter(mainGui))
57
59
 
58
60
  # Buttons
59
61
  self.tbProject = QToolButton(self)
@@ -67,7 +69,7 @@ class GuiSideBar(QWidget):
67
69
  self.tbNovel.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.NOVEL))
68
70
 
69
71
  self.tbOutline = QToolButton(self)
70
- self.tbOutline.setToolTip(f"{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
72
+ self.tbOutline.setToolTip("{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
71
73
  self.tbOutline.setIconSize(iconSize)
72
74
  self.tbOutline.clicked.connect(lambda: self.viewChangeRequested.emit(nwView.OUTLINE))
73
75
 
@@ -111,7 +113,7 @@ class GuiSideBar(QWidget):
111
113
  self.outerBox.addWidget(self.tbDetails)
112
114
  self.outerBox.addWidget(self.tbStats)
113
115
  self.outerBox.addWidget(self.tbSettings)
114
- self.outerBox.setContentsMargins(0, 0, CONFIG.pxInt(2), 0)
116
+ self.outerBox.setContentsMargins(0, 0, 0, 0)
115
117
  self.outerBox.setSpacing(CONFIG.pxInt(4))
116
118
 
117
119
  self.setLayout(self.outerBox)
@@ -131,7 +133,7 @@ class GuiSideBar(QWidget):
131
133
  buttonStyle = (
132
134
  "QToolButton {{padding: {0}px; border: none; background: transparent;}} "
133
135
  "QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
134
- ).format(CONFIG.pxInt(4), fadeCol.red(), fadeCol.green(), fadeCol.blue())
136
+ ).format(CONFIG.pxInt(6), fadeCol.red(), fadeCol.green(), fadeCol.blue())
135
137
  buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}"
136
138
 
137
139
  self.tbProject.setIcon(SHARED.theme.getIcon("view_editor"))
@@ -162,7 +164,7 @@ class GuiSideBar(QWidget):
162
164
 
163
165
  class _PopRightMenu(QMenu):
164
166
 
165
- def event(self, event: QEvent):
167
+ def event(self, event: QEvent) -> bool:
166
168
  """Overload the show event and move the menu popup location."""
167
169
  if event.type() == QEvent.Show:
168
170
  parent = self.parent()
@@ -3,10 +3,10 @@ novelWriter – GUI Main Window Status Bar
3
3
  ========================================
4
4
 
5
5
  File History:
6
- Created: 2019-04-20 [0.0.1]
6
+ Created: 2019-04-20 [0.0.1] GuiMainStatus
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2023, Veronica Berglyd Olsen
9
+ Copyright 2018–2024, Veronica Berglyd Olsen
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -27,9 +27,10 @@ import logging
27
27
 
28
28
  from time import time
29
29
  from typing import TYPE_CHECKING, Literal
30
+ from datetime import datetime
30
31
 
31
- from PyQt5.QtCore import pyqtSlot, QLocale
32
32
  from PyQt5.QtGui import QColor
33
+ from PyQt5.QtCore import pyqtSlot, QLocale
33
34
  from PyQt5.QtWidgets import qApp, QStatusBar, QLabel
34
35
 
35
36
  from novelwriter import CONFIG, SHARED
@@ -50,8 +51,9 @@ class GuiMainStatus(QStatusBar):
50
51
 
51
52
  logger.debug("Create: GuiMainStatus")
52
53
 
53
- self._refTime = -1.0
54
+ self._refTime = -1.0
54
55
  self._userIdle = False
56
+ self._debugInfo = False
55
57
 
56
58
  colNone = QColor(*SHARED.theme.statNone)
57
59
  colSaved = QColor(*SHARED.theme.statSaved)
@@ -97,7 +99,7 @@ class GuiMainStatus(QStatusBar):
97
99
  self.addPermanentWidget(self.statsText)
98
100
 
99
101
  # The Session Clock
100
- # Set the mimimum width so the label doesn't rescale every second
102
+ # Set the minimum width so the label doesn't rescale every second
101
103
  self.timeIcon = QLabel()
102
104
  self.timeText = QLabel("")
103
105
  self.timeText.setToolTip(self.tr("Session Time"))
@@ -223,4 +225,45 @@ class GuiMainStatus(QStatusBar):
223
225
  self.setDocumentStatus(StatusLED.S_BAD if status else StatusLED.S_GOOD)
224
226
  return
225
227
 
228
+ ##
229
+ # Debug
230
+ ##
231
+
232
+ def memInfo(self) -> None: # pragma: no cover
233
+ """Display memory info on the status bar. This is used to
234
+ investigate memory usage and Qt widgets that get left in memory.
235
+ Enabled by the --meminfo command line flag.
236
+
237
+ By default, this tracks memory usage diff after launch. To track
238
+ full memory usage, set environment variable PYTHONTRACEMALLOC=1
239
+ before starting novelWriter.
240
+ """
241
+ import tracemalloc
242
+ from collections import Counter
243
+
244
+ widgets = qApp.allWidgets()
245
+ if not self._debugInfo:
246
+ if tracemalloc.is_tracing():
247
+ self._traceMallocRef = "Total"
248
+ else:
249
+ self._traceMallocRef = "Relative"
250
+ tracemalloc.start()
251
+ self._debugInfo = True
252
+ self._wCounts = Counter([type(x).__name__ for x in widgets])
253
+
254
+ if hasattr(self, "_wCounts"):
255
+ diff = Counter([type(x).__name__ for x in widgets]) - self._wCounts
256
+ for name, count in diff.items():
257
+ logger.debug("Widget '%s': +%d", name, count)
258
+
259
+ mem = tracemalloc.get_traced_memory()
260
+ stamp = datetime.now().strftime("%H:%M:%S")
261
+ self.showMessage((
262
+ f"Debug [{stamp}]"
263
+ f" \u2013 Widgets: {len(widgets)}"
264
+ f" \u2013 {self._traceMallocRef} Memory: {mem[0]:n}"
265
+ f" \u2013 Peak: {mem[1]:n}"
266
+ ), 6000)
267
+ return
268
+
226
269
  # END Class GuiMainStatus
novelwriter/gui/theme.py CHANGED
@@ -7,7 +7,7 @@ Created: 2019-05-18 [0.1.3] GuiTheme
7
7
  Created: 2019-11-08 [0.4] GuiIcons
8
8
 
9
9
  This file is a part of novelWriter
10
- Copyright 2018–2023, Veronica Berglyd Olsen
10
+ Copyright 2018–2024, Veronica Berglyd Olsen
11
11
 
12
12
  This program is free software: you can redistribute it and/or modify
13
13
  it under the terms of the GNU General Public License as published by
@@ -133,6 +133,7 @@ class GuiTheme:
133
133
  self.getToggleIcon = self.iconCache.getToggleIcon
134
134
  self.loadDecoration = self.iconCache.loadDecoration
135
135
  self.getHeaderDecoration = self.iconCache.getHeaderDecoration
136
+ self.getHeaderDecorationNarrow = self.iconCache.getHeaderDecorationNarrow
136
137
 
137
138
  # Extract Other Info
138
139
  self.guiDPI = qApp.primaryScreen().logicalDotsPerInchX()
@@ -459,13 +460,13 @@ class GuiIcons:
459
460
  "search_regex", "search_word",
460
461
 
461
462
  # Format Icons
462
- "fmt_bold", "fmt_italic", "fmt_mode-md", "fmt_mode-sc", "fmt_strike", "fmt_subscript",
463
- "fmt_superscript", "fmt_underline",
463
+ "fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_strike", "fmt_strike-md",
464
+ "fmt_subscript", "fmt_superscript", "fmt_underline",
464
465
 
465
466
  # General Button Icons
466
467
  "add", "backward", "bookmark", "browse", "checked", "close", "cross", "down", "edit",
467
- "export", "forward", "maximise", "menu", "minimise", "noncheckable", "reference",
468
- "refresh", "remove", "revert", "search_replace", "search", "settings", "unchecked", "up",
468
+ "export", "forward", "maximise", "menu", "minimise", "noncheckable", "panel", "refresh",
469
+ "remove", "revert", "search_replace", "search", "settings", "unchecked", "up", "view",
469
470
 
470
471
  # Switches
471
472
  "sticky-on", "sticky-off",
@@ -473,12 +474,13 @@ class GuiIcons:
473
474
 
474
475
  # Decorations
475
476
  "deco_doc_h0", "deco_doc_h1", "deco_doc_h2", "deco_doc_h3", "deco_doc_h4", "deco_doc_more",
477
+ "deco_doc_h0_n", "deco_doc_h1_n", "deco_doc_h2_n", "deco_doc_h3_n", "deco_doc_h4_n",
478
+ "deco_doc_nt_n",
476
479
  }
477
480
 
478
481
  TOGGLE_ICON_KEYS = {
479
- "sticky": ("sticky-on", "sticky-off"),
480
- "bullet": ("bullet-on", "bullet-off"),
481
- "fmt_mode": ("fmt_mode-sc", "fmt_mode-md"),
482
+ "sticky": ("sticky-on", "sticky-off"),
483
+ "bullet": ("bullet-on", "bullet-off"),
482
484
  }
483
485
 
484
486
  IMAGE_MAP = {
@@ -493,6 +495,7 @@ class GuiIcons:
493
495
  self._qIcons: dict[str, QIcon] = {}
494
496
  self._themeMap: dict[str, Path] = {}
495
497
  self._headerDec: list[QPixmap] = []
498
+ self._headerDecNarrow: list[QPixmap] = []
496
499
 
497
500
  # Icon Theme Path
498
501
  self._confName = "icons.conf"
@@ -580,6 +583,7 @@ class GuiIcons:
580
583
  self._qIcons[iconKey] = qIcon
581
584
 
582
585
  self._headerDec = []
586
+ self._headerDecNarrow = []
583
587
 
584
588
  return True
585
589
 
@@ -680,6 +684,20 @@ class GuiIcons:
680
684
  ]
681
685
  return self._headerDec[minmax(hLevel, 0, 4)]
682
686
 
687
+ def getHeaderDecorationNarrow(self, hLevel: int) -> QPixmap:
688
+ """Get the narrow decoration for a specific header level."""
689
+ if not self._headerDecNarrow:
690
+ iPx = self.mainTheme.baseIconSize
691
+ self._headerDecNarrow = [
692
+ self.loadDecoration("deco_doc_h0_n", h=iPx),
693
+ self.loadDecoration("deco_doc_h1_n", h=iPx),
694
+ self.loadDecoration("deco_doc_h2_n", h=iPx),
695
+ self.loadDecoration("deco_doc_h3_n", h=iPx),
696
+ self.loadDecoration("deco_doc_h4_n", h=iPx),
697
+ self.loadDecoration("deco_doc_nt_n", h=iPx),
698
+ ]
699
+ return self._headerDecNarrow[minmax(hLevel, 0, 5)]
700
+
683
701
  ##
684
702
  # Internal Functions
685
703
  ##