novelWriter 2.2rc1__py3-none-any.whl → 2.3__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 (162) hide show
  1. {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/METADATA +1 -1
  2. {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/RECORD +149 -132
  3. {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/WHEEL +1 -1
  4. novelWriter-2.3.dist-info/entry_points.txt +2 -0
  5. novelwriter/__init__.py +11 -6
  6. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  7. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  8. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  9. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  10. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  11. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  12. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  13. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  14. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  15. novelwriter/assets/i18n/project_de_DE.json +1 -0
  16. novelwriter/assets/i18n/project_en_US.json +1 -0
  17. novelwriter/assets/i18n/project_es_419.json +11 -0
  18. novelwriter/assets/i18n/project_fr_FR.json +11 -0
  19. novelwriter/assets/i18n/project_it_IT.json +11 -0
  20. novelwriter/assets/i18n/project_ja_JP.json +2 -1
  21. novelwriter/assets/i18n/project_nb_NO.json +1 -0
  22. novelwriter/assets/i18n/project_nl_NL.json +11 -0
  23. novelwriter/assets/i18n/project_pt_BR.json +11 -0
  24. novelwriter/assets/i18n/project_zh_CN.json +11 -0
  25. novelwriter/assets/icons/typicons_dark/icons.conf +11 -2
  26. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +6 -0
  27. novelwriter/assets/icons/typicons_dark/mixed_import.svg +5 -0
  28. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
  29. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
  30. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
  31. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
  32. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
  33. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
  34. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
  35. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
  36. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
  37. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +4 -0
  38. novelwriter/assets/icons/typicons_dark/typ_document.svg +4 -0
  39. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +4 -0
  40. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +9 -0
  41. novelwriter/assets/icons/typicons_light/icons.conf +11 -2
  42. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +6 -0
  43. novelwriter/assets/icons/typicons_light/mixed_import.svg +5 -0
  44. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
  45. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
  46. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
  47. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
  48. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
  49. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
  50. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
  51. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
  52. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
  53. novelwriter/assets/icons/typicons_light/typ_document-add.svg +4 -0
  54. novelwriter/assets/icons/typicons_light/typ_document.svg +4 -0
  55. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +4 -0
  56. novelwriter/assets/icons/typicons_light/typ_th-list.svg +9 -0
  57. novelwriter/assets/images/novelwriter-text-dark.svg +4 -0
  58. novelwriter/assets/images/novelwriter-text-light.svg +4 -0
  59. novelwriter/assets/images/welcome-dark.jpg +0 -0
  60. novelwriter/assets/images/welcome-light.jpg +0 -0
  61. novelwriter/assets/manual.pdf +0 -0
  62. novelwriter/assets/sample.zip +0 -0
  63. novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
  64. novelwriter/assets/syntax/default_dark.conf +1 -0
  65. novelwriter/assets/syntax/default_light.conf +1 -0
  66. novelwriter/assets/syntax/grey_dark.conf +1 -0
  67. novelwriter/assets/syntax/grey_light.conf +1 -0
  68. novelwriter/assets/syntax/light_owl.conf +1 -0
  69. novelwriter/assets/syntax/night_owl.conf +1 -0
  70. novelwriter/assets/syntax/solarized_dark.conf +1 -0
  71. novelwriter/assets/syntax/solarized_light.conf +1 -0
  72. novelwriter/assets/syntax/tango.conf +23 -0
  73. novelwriter/assets/syntax/tomorrow.conf +1 -0
  74. novelwriter/assets/syntax/tomorrow_night.conf +1 -0
  75. novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
  76. novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
  77. novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
  78. novelwriter/assets/text/credits_en.htm +4 -2
  79. novelwriter/assets/themes/cyberpunk_night.conf +29 -0
  80. novelwriter/assets/themes/default_dark.conf +2 -2
  81. novelwriter/assets/themes/default_light.conf +2 -2
  82. novelwriter/common.py +64 -66
  83. novelwriter/config.py +39 -44
  84. novelwriter/constants.py +39 -17
  85. novelwriter/core/buildsettings.py +8 -8
  86. novelwriter/core/coretools.py +198 -157
  87. novelwriter/core/docbuild.py +7 -4
  88. novelwriter/core/document.py +7 -7
  89. novelwriter/core/index.py +90 -57
  90. novelwriter/core/item.py +23 -5
  91. novelwriter/core/options.py +11 -10
  92. novelwriter/core/project.py +73 -47
  93. novelwriter/core/projectdata.py +3 -16
  94. novelwriter/core/projectxml.py +14 -42
  95. novelwriter/core/sessions.py +4 -3
  96. novelwriter/core/spellcheck.py +6 -4
  97. novelwriter/core/status.py +5 -4
  98. novelwriter/core/storage.py +183 -141
  99. novelwriter/core/tohtml.py +6 -4
  100. novelwriter/core/tokenizer.py +110 -83
  101. novelwriter/core/tomd.py +2 -2
  102. novelwriter/core/toodt.py +41 -31
  103. novelwriter/core/tree.py +5 -4
  104. novelwriter/dialogs/about.py +88 -179
  105. novelwriter/dialogs/docmerge.py +30 -20
  106. novelwriter/dialogs/docsplit.py +33 -22
  107. novelwriter/dialogs/editlabel.py +20 -8
  108. novelwriter/dialogs/preferences.py +562 -725
  109. novelwriter/dialogs/{projsettings.py → projectsettings.py} +301 -270
  110. novelwriter/dialogs/quotes.py +47 -36
  111. novelwriter/dialogs/wordlist.py +128 -59
  112. novelwriter/enum.py +25 -22
  113. novelwriter/error.py +2 -2
  114. novelwriter/extensions/circularprogress.py +12 -12
  115. novelwriter/extensions/configlayout.py +185 -146
  116. novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
  117. novelwriter/extensions/modified.py +81 -0
  118. novelwriter/extensions/novelselector.py +27 -13
  119. novelwriter/extensions/pagedsidebar.py +15 -20
  120. novelwriter/extensions/simpleprogress.py +8 -9
  121. novelwriter/extensions/statusled.py +9 -9
  122. novelwriter/extensions/switch.py +32 -64
  123. novelwriter/extensions/switchbox.py +2 -7
  124. novelwriter/extensions/versioninfo.py +153 -0
  125. novelwriter/gui/doceditor.py +250 -214
  126. novelwriter/gui/dochighlight.py +66 -94
  127. novelwriter/gui/docviewer.py +71 -98
  128. novelwriter/gui/docviewerpanel.py +140 -47
  129. novelwriter/gui/editordocument.py +3 -3
  130. novelwriter/gui/itemdetails.py +9 -9
  131. novelwriter/gui/mainmenu.py +47 -47
  132. novelwriter/gui/noveltree.py +53 -61
  133. novelwriter/gui/outline.py +100 -76
  134. novelwriter/gui/projtree.py +246 -112
  135. novelwriter/gui/sidebar.py +9 -8
  136. novelwriter/gui/statusbar.py +49 -7
  137. novelwriter/gui/theme.py +74 -76
  138. novelwriter/guimain.py +175 -330
  139. novelwriter/shared.py +68 -30
  140. novelwriter/tools/dictionaries.py +7 -8
  141. novelwriter/tools/lipsum.py +34 -28
  142. novelwriter/tools/manusbuild.py +3 -4
  143. novelwriter/tools/manuscript.py +25 -32
  144. novelwriter/tools/manussettings.py +194 -225
  145. novelwriter/tools/noveldetails.py +525 -0
  146. novelwriter/tools/welcome.py +819 -0
  147. novelwriter/tools/writingstats.py +26 -13
  148. novelWriter-2.2rc1.dist-info/entry_points.txt +0 -5
  149. novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
  150. novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
  151. novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
  152. novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
  153. novelwriter/assets/images/wizard-back.jpg +0 -0
  154. novelwriter/assets/text/gplv3_en.htm +0 -641
  155. novelwriter/assets/text/release_notes.htm +0 -17
  156. novelwriter/dialogs/projdetails.py +0 -525
  157. novelwriter/dialogs/projload.py +0 -298
  158. novelwriter/dialogs/updates.py +0 -182
  159. novelwriter/extensions/pageddialog.py +0 -130
  160. novelwriter/tools/projwizard.py +0 -478
  161. {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/LICENSE.md +0 -0
  162. {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,10 @@ novelWriter – GUI About Box
3
3
  ===========================
4
4
 
5
5
  File History:
6
- Created: 2020-05-21 [0.5.2]
6
+ Created: 2020-05-21 [0.5.2] GuiAbout
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
@@ -24,226 +24,135 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
24
24
  from __future__ import annotations
25
25
 
26
26
  import logging
27
- import novelwriter
28
27
 
29
- from datetime import datetime
30
-
31
- from PyQt5.QtGui import QCursor
28
+ from PyQt5.QtGui import QCloseEvent, QColor
32
29
  from PyQt5.QtCore import Qt
33
30
  from PyQt5.QtWidgets import (
34
- qApp, QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTabWidget,
35
- QTextBrowser, QVBoxLayout, QWidget
31
+ QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTextBrowser, QVBoxLayout,
32
+ QWidget
36
33
  )
37
34
 
38
35
  from novelwriter import CONFIG, SHARED
39
36
  from novelwriter.common import readTextFile
40
- from novelwriter.constants import nwConst
37
+ from novelwriter.extensions.configlayout import NColourLabel
38
+ from novelwriter.extensions.versioninfo import VersionInfoWidget
41
39
 
42
40
  logger = logging.getLogger(__name__)
43
41
 
44
42
 
45
43
  class GuiAbout(QDialog):
46
44
 
47
- def __init__(self, parent: QWidget):
45
+ def __init__(self, parent: QWidget) -> None:
48
46
  super().__init__(parent=parent)
49
47
 
50
48
  logger.debug("Create: GuiAbout")
51
49
  self.setObjectName("GuiAbout")
52
50
 
53
- self.outerBox = QVBoxLayout()
54
- self.innerBox = QHBoxLayout()
55
- self.innerBox.setSpacing(CONFIG.pxInt(16))
56
-
57
51
  self.setWindowTitle(self.tr("About novelWriter"))
58
- self.setMinimumWidth(CONFIG.pxInt(650))
59
- self.setMinimumHeight(CONFIG.pxInt(600))
60
-
61
- nPx = CONFIG.pxInt(96)
62
- self.nwIcon = QLabel()
63
- self.nwIcon.setPixmap(SHARED.theme.getPixmap("novelwriter", (nPx, nPx)))
64
- self.lblName = QLabel("<b>novelWriter</b>")
65
- self.lblVers = QLabel(f"v{novelwriter.__version__}")
66
- self.lblDate = QLabel(datetime.strptime(novelwriter.__date__, "%Y-%m-%d").strftime("%x"))
67
-
68
- self.leftBox = QVBoxLayout()
69
- self.leftBox.setSpacing(CONFIG.pxInt(4))
70
- self.leftBox.addWidget(self.nwIcon, 0, Qt.AlignCenter)
71
- self.leftBox.addWidget(self.lblName, 0, Qt.AlignCenter)
72
- self.leftBox.addWidget(self.lblVers, 0, Qt.AlignCenter)
73
- self.leftBox.addWidget(self.lblDate, 0, Qt.AlignCenter)
74
- self.leftBox.addStretch(1)
75
- self.innerBox.addLayout(self.leftBox)
76
-
77
- # Pages
78
- self.pageAbout = QTextBrowser()
79
- self.pageAbout.setOpenExternalLinks(True)
80
- self.pageAbout.document().setDocumentMargin(CONFIG.pxInt(16))
81
-
82
- self.pageNotes = QTextBrowser()
83
- self.pageNotes.setOpenExternalLinks(True)
84
- self.pageNotes.document().setDocumentMargin(CONFIG.pxInt(16))
85
-
86
- self.pageCredits = QTextBrowser()
87
- self.pageCredits.setOpenExternalLinks(True)
88
- self.pageCredits.document().setDocumentMargin(CONFIG.pxInt(16))
89
-
90
- self.pageLicense = QTextBrowser()
91
- self.pageLicense.setOpenExternalLinks(True)
92
- self.pageLicense.document().setDocumentMargin(CONFIG.pxInt(16))
93
-
94
- # Main Tab Area
95
- self.tabBox = QTabWidget()
96
- self.tabBox.addTab(self.pageAbout, self.tr("About"))
97
- self.tabBox.addTab(self.pageNotes, self.tr("Release"))
98
- self.tabBox.addTab(self.pageCredits, self.tr("Credits"))
99
- self.tabBox.addTab(self.pageLicense, self.tr("Licence"))
100
- self.innerBox.addWidget(self.tabBox)
101
-
102
- # OK Button
103
- self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
104
- self.buttonBox.accepted.connect(self._doClose)
105
-
106
- self.outerBox.addLayout(self.innerBox)
107
- self.outerBox.addWidget(self.buttonBox)
52
+ self.resize(CONFIG.pxInt(700), CONFIG.pxInt(500))
53
+
54
+ hA = CONFIG.pxInt(8)
55
+ hB = CONFIG.pxInt(16)
56
+ nwH = CONFIG.pxInt(36)
57
+ nwPx = CONFIG.pxInt(128)
58
+
59
+ # Logo and Banner
60
+ self.nwImage = SHARED.theme.loadDecoration("nw-text", h=nwH)
61
+ self.bgColor = QColor(255, 255, 255) if SHARED.theme.isLightTheme else QColor(54, 54, 54)
62
+
63
+ self.nwLogo = QLabel(self)
64
+ self.nwLogo.setPixmap(SHARED.theme.getPixmap("novelwriter", (nwPx, nwPx)))
65
+
66
+ self.nwLabel = QLabel(self)
67
+ self.nwLabel.setPixmap(self.nwImage)
68
+
69
+ self.nwInfo = VersionInfoWidget(self)
70
+
71
+ self.nwLicence = QLabel(self.tr("This application is licenced under {0}").format(
72
+ "<a href='https://www.gnu.org/licenses/gpl-3.0.html'>GPL v3.0</a>"
73
+ ))
74
+ self.nwLicence.setOpenExternalLinks(True)
75
+
76
+ # Credits
77
+ self.lblCredits = NColourLabel(
78
+ self.tr("Credits"), scale=1.6, parent=self, bold=True
79
+ )
80
+
81
+ self.txtCredits = QTextBrowser(self)
82
+ self.txtCredits.setOpenExternalLinks(True)
83
+ self.txtCredits.document().setDocumentMargin(0)
84
+ self.txtCredits.setViewportMargins(0, hA, hA, 0)
85
+
86
+ # Buttons
87
+ self.btnBox = QDialogButtonBox(QDialogButtonBox.Close, self)
88
+ self.btnBox.rejected.connect(self.close)
89
+
90
+ # Assemble
91
+ self.innerBox = QVBoxLayout()
92
+ self.innerBox.addSpacing(hB)
93
+ self.innerBox.addWidget(self.nwLabel)
94
+ self.innerBox.addWidget(self.nwInfo)
95
+ self.innerBox.addSpacing(hA)
96
+ self.innerBox.addWidget(self.nwLicence)
97
+ self.innerBox.addSpacing(hA)
98
+ self.innerBox.addWidget(self.lblCredits)
99
+ self.innerBox.addWidget(self.txtCredits)
100
+ self.innerBox.addSpacing(hB)
101
+ self.innerBox.addWidget(self.btnBox)
102
+
103
+ topRight = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight
104
+
105
+ self.outerBox = QHBoxLayout()
106
+ self.outerBox.addWidget(self.nwLogo, 0, topRight)
107
+ self.outerBox.addLayout(self.innerBox, 1)
108
+
108
109
  self.setLayout(self.outerBox)
110
+ self.setSizeGripEnabled(True)
111
+ self._setStyleSheet()
109
112
 
110
113
  logger.debug("Ready: GuiAbout")
111
114
 
112
115
  return
113
116
 
114
- def __del__(self): # pragma: no cover
117
+ def __del__(self) -> None: # pragma: no cover
115
118
  logger.debug("Delete: GuiAbout")
116
119
  return
117
120
 
118
- def populateGUI(self):
119
- """Populate tabs with text.
120
- """
121
- qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
122
- self._setStyleSheet()
123
- self._fillAboutPage()
124
- self._fillNotesPage()
121
+ def populateGUI(self) -> None:
122
+ """Populate tabs with text."""
125
123
  self._fillCreditsPage()
126
- self._fillLicensePage()
127
- qApp.restoreOverrideCursor()
128
- return
129
-
130
- def showReleaseNotes(self):
131
- """Show the release notes.
132
- """
133
- self.tabBox.setCurrentWidget(self.pageNotes)
134
124
  return
135
125
 
136
126
  ##
137
- # Internal Functions
127
+ # Events
138
128
  ##
139
129
 
140
- def _fillAboutPage(self):
141
- """Generate the content for the About page.
142
- """
143
- aboutMsg = (
144
- "<h2>{title1}</h2>"
145
- "<p>{copy}</p>"
146
- "<p>{link}</p>"
147
- "<p>{intro}</p>"
148
- "<p>{license1}</p>"
149
- "<p>{license2}</p>"
150
- "<p>{license3}</p>"
151
- ).format(
152
- title1=self.tr("About novelWriter"),
153
- copy=novelwriter.__copyright__,
154
- link=self.tr("Website: {0}").format(
155
- f"<a href='{nwConst.URL_WEB}'>{novelwriter.__domain__}</a>"
156
- ),
157
- intro=self.tr(
158
- "novelWriter is a markdown-like text editor designed for organising and "
159
- "writing novels. It is written in Python 3 with a Qt5 GUI, using PyQt5."
160
- ),
161
- license1=self.tr(
162
- "novelWriter is free software: you can redistribute it and/or modify it "
163
- "under the terms of the GNU General Public License as published by the "
164
- "Free Software Foundation, either version 3 of the License, or (at your "
165
- "option) any later version."
166
- ),
167
- license2=self.tr(
168
- "novelWriter is distributed in the hope that it will be useful, but "
169
- "WITHOUT ANY WARRANTY; without even the implied warranty of "
170
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
171
- ),
172
- license3=self.tr(
173
- "See the Licence tab for the full licence text, or visit the "
174
- "GNU website at {0} for more details."
175
- ).format(
176
- "<a href='https://www.gnu.org/licenses/gpl-3.0.html'>GPL v3.0</a>"
177
- ),
178
- )
179
-
180
- self.pageAbout.setHtml(aboutMsg)
181
-
130
+ def closeEvent(self, event: QCloseEvent) -> None:
131
+ """Capture the close event and perform cleanup."""
132
+ event.accept()
133
+ self.deleteLater()
182
134
  return
183
135
 
184
- def _fillNotesPage(self):
185
- """Load the content for the Release Notes page.
186
- """
187
- docPath = CONFIG.assetPath("text") / "release_notes.htm"
188
- docText = readTextFile(docPath)
189
- if docText:
190
- self.pageNotes.setHtml(docText)
191
- else:
192
- self.pageNotes.setHtml("Error loading release notes text ...")
193
- return
136
+ ##
137
+ # Internal Functions
138
+ ##
194
139
 
195
- def _fillCreditsPage(self):
196
- """Load the content for the Credits page.
197
- """
140
+ def _fillCreditsPage(self) -> None:
141
+ """Load the content for the Credits page."""
198
142
  docPath = CONFIG.assetPath("text") / "credits_en.htm"
199
143
  docText = readTextFile(docPath)
200
144
  if docText:
201
- self.pageCredits.setHtml(docText)
145
+ self.txtCredits.setHtml(docText)
202
146
  else:
203
- self.pageCredits.setHtml("Error loading credits text ...")
204
- return
205
-
206
- def _fillLicensePage(self):
207
- """Load the content for the Licence page.
208
- """
209
- docPath = CONFIG.assetPath("text") / "gplv3_en.htm"
210
- docText = readTextFile(docPath)
211
- if docText:
212
- self.pageLicense.setHtml(docText)
213
- else:
214
- self.pageLicense.setHtml("Error loading licence text ...")
215
- return
216
-
217
- def _setStyleSheet(self):
218
- """Set stylesheet for all browser tabs
219
- """
220
- styleSheet = (
221
- "h1, h2, h3, h4 {{"
222
- " color: rgb({hColR},{hColG},{hColB});"
223
- "}}\n"
224
- "a {{"
225
- " color: rgb({hColR},{hColG},{hColB});"
226
- "}}\n"
227
- ".alt {{"
228
- " color: rgb({kColR},{kColG},{kColB});"
229
- "}}\n"
230
- ).format(
231
- hColR=SHARED.theme.colHead[0],
232
- hColG=SHARED.theme.colHead[1],
233
- hColB=SHARED.theme.colHead[2],
234
- kColR=SHARED.theme.colKey[0],
235
- kColG=SHARED.theme.colKey[1],
236
- kColB=SHARED.theme.colKey[2],
237
- )
238
- self.pageAbout.document().setDefaultStyleSheet(styleSheet)
239
- self.pageNotes.document().setDefaultStyleSheet(styleSheet)
240
- self.pageCredits.document().setDefaultStyleSheet(styleSheet)
241
- self.pageLicense.document().setDefaultStyleSheet(styleSheet)
242
-
147
+ self.txtCredits.setHtml("Error loading credits text ...")
243
148
  return
244
149
 
245
- def _doClose(self):
246
- self.close()
150
+ def _setStyleSheet(self) -> None:
151
+ """Set stylesheet for all browser tabs."""
152
+ baseCol = self.palette().window().color()
153
+ self.txtCredits.setStyleSheet((
154
+ "QTextBrowser {{border: none; background: rgb({r},{g},{b});}} "
155
+ ).format(r=baseCol.red(), g=baseCol.green(), b=baseCol.blue()))
247
156
  return
248
157
 
249
158
  # END Class GuiAbout
@@ -3,11 +3,11 @@ novelWriter – GUI Doc Merge Dialog
3
3
  ==================================
4
4
 
5
5
  File History:
6
- Created: 2020-01-23 [0.4.3]
7
- Rewritten: 2022-10-06 [2.0rc1]
6
+ Created: 2020-01-23 [0.4.3] GuiDocMerge
7
+ Rewritten: 2022-10-06 [2.0rc1] GuiDocMerge
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
@@ -26,7 +26,8 @@ from __future__ import annotations
26
26
 
27
27
  import logging
28
28
 
29
- from PyQt5.QtCore import Qt, QSize
29
+ from PyQt5.QtGui import QCloseEvent
30
+ from PyQt5.QtCore import Qt, QSize, pyqtSlot
30
31
  from PyQt5.QtWidgets import (
31
32
  QAbstractItemView, QDialog, QDialogButtonBox, QGridLayout, QLabel,
32
33
  QListWidget, QListWidgetItem, QVBoxLayout, QWidget
@@ -34,7 +35,7 @@ from PyQt5.QtWidgets import (
34
35
 
35
36
  from novelwriter import CONFIG, SHARED
36
37
  from novelwriter.extensions.switch import NSwitch
37
- from novelwriter.extensions.configlayout import NHelpLabel
38
+ from novelwriter.extensions.configlayout import NColourLabel
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
@@ -53,9 +54,10 @@ class GuiDocMerge(QDialog):
53
54
  self._data = {}
54
55
 
55
56
  self.headLabel = QLabel("<b>{0}</b>".format(self.tr("Documents to Merge")))
56
- self.helpLabel = NHelpLabel(self.tr(
57
- "Drag and drop items to change the order, or uncheck to exclude."
58
- ), SHARED.theme.helpText)
57
+ self.helpLabel = NColourLabel(
58
+ self.tr("Drag and drop items to change the order, or uncheck to exclude."),
59
+ SHARED.theme.helpText, parent=self, wrap=True
60
+ )
59
61
 
60
62
  iPx = SHARED.theme.baseIconSize
61
63
  hSp = CONFIG.pxInt(12)
@@ -72,7 +74,7 @@ class GuiDocMerge(QDialog):
72
74
 
73
75
  # Merge Options
74
76
  self.trashLabel = QLabel(self.tr("Move merged items to Trash"))
75
- self.trashSwitch = NSwitch(width=2*iPx, height=iPx)
77
+ self.trashSwitch = NSwitch(self, height=iPx)
76
78
 
77
79
  self.optBox = QGridLayout()
78
80
  self.optBox.addWidget(self.trashLabel, 0, 0)
@@ -108,13 +110,12 @@ class GuiDocMerge(QDialog):
108
110
 
109
111
  return
110
112
 
111
- def __del__(self): # pragma: no cover
113
+ def __del__(self) -> None: # pragma: no cover
112
114
  logger.debug("Delete: GuiDocMerge")
113
115
  return
114
116
 
115
- def getData(self):
116
- """Return the user's choices.
117
- """
117
+ def getData(self) -> dict:
118
+ """Return the user's choices."""
118
119
  finalItems = []
119
120
  for i in range(self.listBox.count()):
120
121
  item = self.listBox.item(i)
@@ -127,12 +128,22 @@ class GuiDocMerge(QDialog):
127
128
  return self._data
128
129
 
129
130
  ##
130
- # Slots
131
+ # Events
131
132
  ##
132
133
 
133
- def _resetList(self):
134
- """Reset the content of the list box to its original state.
135
- """
134
+ def closeEvent(self, event: QCloseEvent) -> None:
135
+ """Capture the close event and perform cleanup."""
136
+ event.accept()
137
+ self.deleteLater()
138
+ return
139
+
140
+ ##
141
+ # Private Slots
142
+ ##
143
+
144
+ @pyqtSlot()
145
+ def _resetList(self) -> None:
146
+ """Reset the content of the list box to its original state."""
136
147
  logger.debug("Resetting list box content")
137
148
  sHandle = self._data.get("sHandle", None)
138
149
  itemList = self._data.get("origItems", [])
@@ -143,9 +154,8 @@ class GuiDocMerge(QDialog):
143
154
  # Internal Functions
144
155
  ##
145
156
 
146
- def _loadContent(self, sHandle, itemList):
147
- """Load content from a given list of items.
148
- """
157
+ def _loadContent(self, sHandle: str, itemList: list[str]) -> None:
158
+ """Load content from a given list of items."""
149
159
  self._data = {}
150
160
  self._data["sHandle"] = sHandle
151
161
  self._data["origItems"] = itemList
@@ -3,11 +3,11 @@ novelWriter – GUI Doc Split Dialog
3
3
  ==================================
4
4
 
5
5
  File History:
6
- Created: 2020-02-01 [0.4.3]
7
- Rewritten: 2022-10-12 [2.0rc1]
6
+ Created: 2020-02-01 [0.4.3] GuiDocSplit
7
+ Rewritten: 2022-10-12 [2.0rc1] GuiDocSplit
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
@@ -26,15 +26,16 @@ from __future__ import annotations
26
26
 
27
27
  import logging
28
28
 
29
- from PyQt5.QtCore import Qt
29
+ from PyQt5.QtGui import QCloseEvent
30
+ from PyQt5.QtCore import Qt, pyqtSlot
30
31
  from PyQt5.QtWidgets import (
31
- QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
32
- QListWidgetItem, QDialogButtonBox, QLabel, QGridLayout
32
+ QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGridLayout,
33
+ QLabel, QListWidget, QListWidgetItem, QVBoxLayout, QWidget
33
34
  )
34
35
 
35
36
  from novelwriter import CONFIG, SHARED
36
37
  from novelwriter.extensions.switch import NSwitch
37
- from novelwriter.extensions.configlayout import NHelpLabel
38
+ from novelwriter.extensions.configlayout import NColourLabel
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
@@ -45,7 +46,7 @@ class GuiDocSplit(QDialog):
45
46
  LEVEL_ROLE = Qt.ItemDataRole.UserRole + 1
46
47
  LABEL_ROLE = Qt.ItemDataRole.UserRole + 2
47
48
 
48
- def __init__(self, parent, sHandle):
49
+ def __init__(self, parent: QWidget, sHandle: str) -> None:
49
50
  super().__init__(parent=parent)
50
51
 
51
52
  logger.debug("Create: GuiDocSplit")
@@ -57,9 +58,9 @@ class GuiDocSplit(QDialog):
57
58
  self.setWindowTitle(self.tr("Split Document"))
58
59
 
59
60
  self.headLabel = QLabel("<b>{0}</b>".format(self.tr("Document Headers")))
60
- self.helpLabel = NHelpLabel(
61
+ self.helpLabel = NColourLabel(
61
62
  self.tr("Select the maximum level to split into files."),
62
- SHARED.theme.helpText
63
+ SHARED.theme.helpText, parent=self, wrap=True
63
64
  )
64
65
 
65
66
  # Values
@@ -91,15 +92,15 @@ class GuiDocSplit(QDialog):
91
92
 
92
93
  # Split Options
93
94
  self.folderLabel = QLabel(self.tr("Split into a new folder"))
94
- self.folderSwitch = NSwitch(width=2*iPx, height=iPx)
95
+ self.folderSwitch = NSwitch(self, height=iPx)
95
96
  self.folderSwitch.setChecked(intoFolder)
96
97
 
97
98
  self.hierarchyLabel = QLabel(self.tr("Create document hierarchy"))
98
- self.hierarchySwitch = NSwitch(width=2*iPx, height=iPx)
99
+ self.hierarchySwitch = NSwitch(self, height=iPx)
99
100
  self.hierarchySwitch.setChecked(docHierarchy)
100
101
 
101
102
  self.trashLabel = QLabel(self.tr("Move split document to Trash"))
102
- self.trashSwitch = NSwitch(width=2*iPx, height=iPx)
103
+ self.trashSwitch = NSwitch(self, height=iPx)
103
104
 
104
105
  self.optBox = QGridLayout()
105
106
  self.optBox.addWidget(self.folderLabel, 0, 0)
@@ -138,11 +139,11 @@ class GuiDocSplit(QDialog):
138
139
 
139
140
  return
140
141
 
141
- def __del__(self): # pragma: no cover
142
+ def __del__(self) -> None: # pragma: no cover
142
143
  logger.debug("Delete: GuiDocSplit")
143
144
  return
144
145
 
145
- def getData(self):
146
+ def getData(self) -> tuple[dict, list]:
146
147
  """Return the user's choices. Also save the users options for
147
148
  the next time the dialog is used.
148
149
  """
@@ -167,6 +168,7 @@ class GuiDocSplit(QDialog):
167
168
  self._data["docHierarchy"] = docHierarchy
168
169
  self._data["moveToTrash"] = moveToTrash
169
170
 
171
+ logger.debug("Saving State: GuiDocSplit")
170
172
  pOptions = SHARED.project.options
171
173
  pOptions.setValue("GuiDocSplit", "spLevel", spLevel)
172
174
  pOptions.setValue("GuiDocSplit", "intoFolder", intoFolder)
@@ -175,12 +177,22 @@ class GuiDocSplit(QDialog):
175
177
  return self._data, self._text
176
178
 
177
179
  ##
178
- # Slots
180
+ # Events
179
181
  ##
180
182
 
181
- def _reloadList(self):
182
- """Reload the content of the list box.
183
- """
183
+ def closeEvent(self, event: QCloseEvent) -> None:
184
+ """Capture the close event and perform cleanup."""
185
+ event.accept()
186
+ self.deleteLater()
187
+ return
188
+
189
+ ##
190
+ # Private Slots
191
+ ##
192
+
193
+ @pyqtSlot()
194
+ def _reloadList(self) -> None:
195
+ """Reload the content of the list box."""
184
196
  sHandle = self._data.get("sHandle", None)
185
197
  self._loadContent(sHandle)
186
198
  return
@@ -189,9 +201,8 @@ class GuiDocSplit(QDialog):
189
201
  # Internal Functions
190
202
  ##
191
203
 
192
- def _loadContent(self, sHandle):
193
- """Load content from a given source item.
194
- """
204
+ def _loadContent(self, sHandle: str) -> None:
205
+ """Load content from a given source item."""
195
206
  self._data = {}
196
207
  self._data["sHandle"] = sHandle
197
208
 
@@ -3,10 +3,10 @@ novelWriter – Edit Label Dialog
3
3
  ===============================
4
4
 
5
5
  File History:
6
- Created: 2022-06-11 [2.0rc1]
6
+ Created: 2022-06-11 [2.0rc1] GuiEditLabel
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
@@ -26,7 +26,8 @@ from __future__ import annotations
26
26
  import logging
27
27
 
28
28
  from PyQt5.QtWidgets import (
29
- QDialog, QVBoxLayout, QLineEdit, QLabel, QDialogButtonBox, QHBoxLayout
29
+ QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout,
30
+ QWidget
30
31
  )
31
32
 
32
33
  from novelwriter import CONFIG
@@ -36,9 +37,10 @@ logger = logging.getLogger(__name__)
36
37
 
37
38
  class GuiEditLabel(QDialog):
38
39
 
39
- def __init__(self, parent, text=""):
40
+ def __init__(self, parent: QWidget, text: str = "") -> None:
40
41
  super().__init__(parent=parent)
41
42
 
43
+ logger.debug("Create: GuiEditLabel")
42
44
  self.setObjectName("GuiEditLabel")
43
45
  self.setWindowTitle(self.tr("Item Label"))
44
46
 
@@ -46,7 +48,7 @@ class GuiEditLabel(QDialog):
46
48
  mSp = CONFIG.pxInt(12)
47
49
 
48
50
  # Item Label
49
- self.labelValue = QLineEdit()
51
+ self.labelValue = QLineEdit(self)
50
52
  self.labelValue.setMinimumWidth(mVd)
51
53
  self.labelValue.setMaxLength(200)
52
54
  self.labelValue.setText(text)
@@ -70,16 +72,26 @@ class GuiEditLabel(QDialog):
70
72
 
71
73
  self.setLayout(self.outerBox)
72
74
 
75
+ logger.debug("Ready: GuiEditLabel")
76
+
77
+ return
78
+
79
+ def __del__(self) -> None: # pragma: no cover
80
+ logger.debug("Delete: GuiEditLabel")
73
81
  return
74
82
 
75
83
  @property
76
- def itemLabel(self):
84
+ def itemLabel(self) -> str:
77
85
  return self.labelValue.text()
78
86
 
79
87
  @classmethod
80
- def getLabel(cls, parent, text):
88
+ def getLabel(cls, parent: QWidget, text: str) -> tuple[str, bool]:
89
+ """Pop the dialog and return the result."""
81
90
  cls = GuiEditLabel(parent, text=text)
82
91
  cls.exec_()
83
- return cls.itemLabel, cls.result() == QDialog.Accepted
92
+ label = cls.itemLabel
93
+ accepted = cls.result() == QDialog.Accepted
94
+ cls.deleteLater()
95
+ return label, accepted
84
96
 
85
97
  # END Class GuiEditLabel