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
@@ -1,525 +0,0 @@
1
- """
2
- novelWriter – GUI Project Details
3
- =================================
4
-
5
- File History:
6
- Created: 2021-01-03 [1.1rc1]
7
-
8
- This file is a part of novelWriter
9
- Copyright 2018–2023, Veronica Berglyd Olsen
10
-
11
- This program is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU General Public License as published by
13
- the Free Software Foundation, either version 3 of the License, or
14
- (at your option) any later version.
15
-
16
- This program is distributed in the hope that it will be useful, but
17
- WITHOUT ANY WARRANTY; without even the implied warranty of
18
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
- General Public License for more details.
20
-
21
- You should have received a copy of the GNU General Public License
22
- along with this program. If not, see <https://www.gnu.org/licenses/>.
23
- """
24
- from __future__ import annotations
25
-
26
- import math
27
- import logging
28
-
29
- from PyQt5.QtCore import Qt, QSize, pyqtSlot
30
- from PyQt5.QtGui import QFont
31
- from PyQt5.QtWidgets import (
32
- QAbstractItemView, QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel,
33
- QLineEdit, QSpinBox, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
34
- )
35
-
36
- from novelwriter import CONFIG, SHARED
37
- from novelwriter.common import formatTime, numberToRoman
38
- from novelwriter.constants import nwUnicode
39
- from novelwriter.extensions.switch import NSwitch
40
- from novelwriter.extensions.pageddialog import NPagedDialog
41
- from novelwriter.extensions.novelselector import NovelSelector
42
-
43
- logger = logging.getLogger(__name__)
44
-
45
-
46
- class GuiProjectDetails(NPagedDialog):
47
-
48
- def __init__(self, parent):
49
- super().__init__(parent=parent)
50
-
51
- logger.debug("Create: GuiProjectDetails")
52
- self.setObjectName("GuiProjectDetails")
53
-
54
- self.setWindowTitle(self.tr("Project Details"))
55
-
56
- wW = CONFIG.pxInt(600)
57
- wH = CONFIG.pxInt(400)
58
- pOptions = SHARED.project.options
59
-
60
- self.setMinimumWidth(wW)
61
- self.setMinimumHeight(wH)
62
- self.resize(
63
- CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "winWidth", wW)),
64
- CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "winHeight", wH))
65
- )
66
-
67
- self.tabMain = GuiProjectDetailsMain(self)
68
- self.tabContents = GuiProjectDetailsContents(self)
69
-
70
- self.addTab(self.tabMain, self.tr("Overview"))
71
- self.addTab(self.tabContents, self.tr("Contents"))
72
-
73
- self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
74
- self.buttonBox.button(QDialogButtonBox.Close)
75
- self.buttonBox.rejected.connect(self._doClose)
76
- self.addControls(self.buttonBox)
77
-
78
- logger.debug("Ready: GuiProjectDetails")
79
-
80
- return
81
-
82
- def __del__(self): # pragma: no cover
83
- logger.debug("Delete: GuiProjectDetails")
84
- return
85
-
86
- def updateValues(self):
87
- """Set all the values of the pages.
88
- """
89
- self.tabMain.updateValues()
90
- self.tabContents.updateValues()
91
- return
92
-
93
- ##
94
- # Slots
95
- ##
96
-
97
- def _doClose(self):
98
- """Save settings and close the dialog.
99
- """
100
- self._saveGuiSettings()
101
- self.close()
102
- return
103
-
104
- ##
105
- # Internal Functions
106
- ##
107
-
108
- def _saveGuiSettings(self):
109
- """Save GUI settings.
110
- """
111
- winWidth = CONFIG.rpxInt(self.width())
112
- winHeight = CONFIG.rpxInt(self.height())
113
-
114
- cColWidth = self.tabContents.getColumnSizes()
115
- widthCol0 = CONFIG.rpxInt(cColWidth[0])
116
- widthCol1 = CONFIG.rpxInt(cColWidth[1])
117
- widthCol2 = CONFIG.rpxInt(cColWidth[2])
118
- widthCol3 = CONFIG.rpxInt(cColWidth[3])
119
- widthCol4 = CONFIG.rpxInt(cColWidth[4])
120
-
121
- wordsPerPage = self.tabContents.wpValue.value()
122
- countFrom = self.tabContents.poValue.value()
123
- clearDouble = self.tabContents.dblValue.isChecked()
124
-
125
- pOptions = SHARED.project.options
126
- pOptions.setValue("GuiProjectDetails", "winWidth", winWidth)
127
- pOptions.setValue("GuiProjectDetails", "winHeight", winHeight)
128
- pOptions.setValue("GuiProjectDetails", "widthCol0", widthCol0)
129
- pOptions.setValue("GuiProjectDetails", "widthCol1", widthCol1)
130
- pOptions.setValue("GuiProjectDetails", "widthCol2", widthCol2)
131
- pOptions.setValue("GuiProjectDetails", "widthCol3", widthCol3)
132
- pOptions.setValue("GuiProjectDetails", "widthCol4", widthCol4)
133
- pOptions.setValue("GuiProjectDetails", "wordsPerPage", wordsPerPage)
134
- pOptions.setValue("GuiProjectDetails", "countFrom", countFrom)
135
- pOptions.setValue("GuiProjectDetails", "clearDouble", clearDouble)
136
-
137
- return
138
-
139
- # END Class GuiProjectDetails
140
-
141
-
142
- class GuiProjectDetailsMain(QWidget):
143
-
144
- def __init__(self, parent):
145
- super().__init__(parent=parent)
146
-
147
- fPx = SHARED.theme.fontPixelSize
148
- fPt = SHARED.theme.fontPointSize
149
- vPx = CONFIG.pxInt(4)
150
- hPx = CONFIG.pxInt(12)
151
-
152
- # Header
153
- # ======
154
-
155
- self.bookTitle = QLabel("")
156
- bookFont = self.bookTitle.font()
157
- bookFont.setPointSizeF(2.2*fPt)
158
- bookFont.setWeight(QFont.Bold)
159
- self.bookTitle.setFont(bookFont)
160
- self.bookTitle.setAlignment(Qt.AlignHCenter)
161
- self.bookTitle.setWordWrap(True)
162
-
163
- self.projName = QLabel("")
164
- workFont = self.projName.font()
165
- workFont.setPointSizeF(0.8*fPt)
166
- workFont.setItalic(True)
167
- self.projName.setFont(workFont)
168
- self.projName.setAlignment(Qt.AlignHCenter)
169
- self.projName.setWordWrap(True)
170
-
171
- self.bookAuthors = QLabel("")
172
- authFont = self.bookAuthors.font()
173
- authFont.setPointSizeF(1.2*fPt)
174
- self.bookAuthors.setFont(authFont)
175
- self.bookAuthors.setAlignment(Qt.AlignHCenter)
176
- self.bookAuthors.setWordWrap(True)
177
-
178
- # Stats
179
- # =====
180
-
181
- self.wordCountLbl = QLabel("<b>%s:</b>" % self.tr("Words"))
182
- self.wordCountVal = QLabel("")
183
-
184
- self.chapCountLbl = QLabel("<b>%s:</b>" % self.tr("Chapters"))
185
- self.chapCountVal = QLabel("")
186
-
187
- self.sceneCountLbl = QLabel("<b>%s:</b>" % self.tr("Scenes"))
188
- self.sceneCountVal = QLabel("")
189
-
190
- self.revCountLbl = QLabel("<b>%s:</b>" % self.tr("Revisions"))
191
- self.revCountVal = QLabel("")
192
-
193
- self.editTimeLbl = QLabel("<b>%s:</b>" % self.tr("Editing Time"))
194
- self.editTimeVal = QLabel("")
195
-
196
- self.statsGrid = QGridLayout()
197
- self.statsGrid.addWidget(self.wordCountLbl, 0, 0, 1, 1, Qt.AlignRight)
198
- self.statsGrid.addWidget(self.wordCountVal, 0, 1, 1, 1, Qt.AlignLeft)
199
- self.statsGrid.addWidget(self.chapCountLbl, 1, 0, 1, 1, Qt.AlignRight)
200
- self.statsGrid.addWidget(self.chapCountVal, 1, 1, 1, 1, Qt.AlignLeft)
201
- self.statsGrid.addWidget(self.sceneCountLbl, 2, 0, 1, 1, Qt.AlignRight)
202
- self.statsGrid.addWidget(self.sceneCountVal, 2, 1, 1, 1, Qt.AlignLeft)
203
- self.statsGrid.addWidget(self.revCountLbl, 3, 0, 1, 1, Qt.AlignRight)
204
- self.statsGrid.addWidget(self.revCountVal, 3, 1, 1, 1, Qt.AlignLeft)
205
- self.statsGrid.addWidget(self.editTimeLbl, 4, 0, 1, 1, Qt.AlignRight)
206
- self.statsGrid.addWidget(self.editTimeVal, 4, 1, 1, 1, Qt.AlignLeft)
207
- self.statsGrid.setHorizontalSpacing(hPx)
208
- self.statsGrid.setVerticalSpacing(vPx)
209
-
210
- # Meta
211
- # ====
212
-
213
- self.projPathLbl = QLabel("<b>%s:</b>" % self.tr("Path"))
214
- self.projPathVal = QLineEdit()
215
- self.projPathVal.setReadOnly(True)
216
-
217
- self.projPathBox = QHBoxLayout()
218
- self.projPathBox.addWidget(self.projPathLbl)
219
- self.projPathBox.addWidget(self.projPathVal)
220
- self.projPathBox.setSpacing(hPx)
221
-
222
- # Assemble
223
- # ========
224
-
225
- self.outerBox = QVBoxLayout()
226
- self.outerBox.addSpacing(fPx)
227
- self.outerBox.addWidget(self.bookTitle)
228
- self.outerBox.addWidget(self.projName)
229
- self.outerBox.addWidget(self.bookAuthors)
230
- self.outerBox.addSpacing(2*fPx)
231
- self.outerBox.addLayout(self.statsGrid)
232
- self.outerBox.addSpacing(fPx)
233
- self.outerBox.addStretch(1)
234
- self.outerBox.addLayout(self.projPathBox)
235
-
236
- self.setLayout(self.outerBox)
237
-
238
- return
239
-
240
- def updateValues(self) -> None:
241
- """Set all the values."""
242
- project = SHARED.project
243
- pIndex = project.index
244
- hCounts = pIndex.getNovelTitleCounts()
245
- nwCount = pIndex.getNovelWordCount()
246
- edTime = project.currentEditTime
247
-
248
- self.bookTitle.setText(project.data.title or project.data.name)
249
- self.projName.setText(self.tr("Project: {0}").format(project.data.name))
250
- self.bookAuthors.setText(self.tr("By {0}").format(project.data.author))
251
-
252
- self.wordCountVal.setText(f"{nwCount:n}")
253
- self.chapCountVal.setText(f"{hCounts[2]:n}")
254
- self.sceneCountVal.setText(f"{hCounts[3]:n}")
255
- self.revCountVal.setText(f"{project.data.saveCount:n}")
256
- self.editTimeVal.setText(formatTime(edTime))
257
-
258
- self.projPathVal.setText(str(project.storage.storagePath))
259
-
260
- return
261
-
262
- # END Class GuiProjectDetailsMain
263
-
264
-
265
- class GuiProjectDetailsContents(QWidget):
266
-
267
- C_TITLE = 0
268
- C_WORDS = 1
269
- C_PAGES = 2
270
- C_PAGE = 3
271
- C_PROG = 4
272
-
273
- def __init__(self, parent):
274
- super().__init__(parent=parent)
275
-
276
- # Internal
277
- self._theToC = []
278
- self._currentRoot = None
279
-
280
- iPx = SHARED.theme.baseIconSize
281
- hPx = CONFIG.pxInt(12)
282
- vPx = CONFIG.pxInt(4)
283
- pOptions = SHARED.project.options
284
-
285
- # Header
286
- # ======
287
-
288
- self.tocLabel = QLabel("<b>%s</b>" % self.tr("Table of Contents"))
289
-
290
- self.novelValue = NovelSelector(self)
291
- self.novelValue.setMinimumWidth(CONFIG.pxInt(200))
292
- self.novelValue.novelSelectionChanged.connect(self._novelValueChanged)
293
-
294
- self.headBox = QHBoxLayout()
295
- self.headBox.addWidget(self.tocLabel)
296
- self.headBox.addWidget(self.novelValue)
297
-
298
- # Contents Tree
299
- # =============
300
-
301
- self.tocTree = QTreeWidget()
302
- self.tocTree.setIconSize(QSize(iPx, iPx))
303
- self.tocTree.setIndentation(0)
304
- self.tocTree.setColumnCount(6)
305
- self.tocTree.setSelectionMode(QAbstractItemView.NoSelection)
306
- self.tocTree.setHeaderLabels([
307
- self.tr("Title"),
308
- self.tr("Words"),
309
- self.tr("Pages"),
310
- self.tr("Page"),
311
- self.tr("Progress"),
312
- ""
313
- ])
314
-
315
- treeHeadItem = self.tocTree.headerItem()
316
- if treeHeadItem:
317
- treeHeadItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
318
- treeHeadItem.setTextAlignment(self.C_PAGES, Qt.AlignRight)
319
- treeHeadItem.setTextAlignment(self.C_PAGE, Qt.AlignRight)
320
- treeHeadItem.setTextAlignment(self.C_PROG, Qt.AlignRight)
321
-
322
- treeHeader = self.tocTree.header()
323
- treeHeader.setStretchLastSection(True)
324
- treeHeader.setMinimumSectionSize(hPx)
325
-
326
- wCol0 = CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol0", 200))
327
- wCol1 = CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol1", 60))
328
- wCol2 = CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol2", 60))
329
- wCol3 = CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol3", 60))
330
- wCol4 = CONFIG.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol4", 90))
331
-
332
- self.tocTree.setColumnWidth(0, wCol0)
333
- self.tocTree.setColumnWidth(1, wCol1)
334
- self.tocTree.setColumnWidth(2, wCol2)
335
- self.tocTree.setColumnWidth(3, wCol3)
336
- self.tocTree.setColumnWidth(4, wCol4)
337
- self.tocTree.setColumnWidth(5, hPx)
338
-
339
- # Options
340
- # =======
341
-
342
- wordsPerPage = pOptions.getInt("GuiProjectDetails", "wordsPerPage", 350)
343
- countFrom = pOptions.getInt("GuiProjectDetails", "countFrom", 1)
344
- clearDouble = pOptions.getBool("GuiProjectDetails", "clearDouble", True)
345
-
346
- wordsHelp = (
347
- self.tr("Typical word count for a 5 by 8 inch book page with 11 pt font is 350.")
348
- )
349
- offsetHelp = (
350
- self.tr("Start counting page numbers from this page.")
351
- )
352
- dblHelp = (
353
- self.tr("Assume a new chapter or partition always start on an odd numbered page.")
354
- )
355
-
356
- self.wpLabel = QLabel(self.tr("Words per page"))
357
- self.wpLabel.setToolTip(wordsHelp)
358
-
359
- self.wpValue = QSpinBox()
360
- self.wpValue.setMinimum(10)
361
- self.wpValue.setMaximum(1000)
362
- self.wpValue.setSingleStep(10)
363
- self.wpValue.setValue(wordsPerPage)
364
- self.wpValue.setToolTip(wordsHelp)
365
- self.wpValue.valueChanged.connect(self._populateTree)
366
-
367
- self.poLabel = QLabel(self.tr("Count pages from"))
368
- self.poLabel.setToolTip(offsetHelp)
369
-
370
- self.poValue = QSpinBox()
371
- self.poValue.setMinimum(1)
372
- self.poValue.setMaximum(9999)
373
- self.poValue.setSingleStep(1)
374
- self.poValue.setValue(countFrom)
375
- self.poValue.setToolTip(offsetHelp)
376
- self.poValue.valueChanged.connect(self._populateTree)
377
-
378
- self.dblLabel = QLabel(self.tr("Clear double pages"))
379
- self.dblLabel.setToolTip(dblHelp)
380
-
381
- self.dblValue = NSwitch(self, 2*iPx, iPx)
382
- self.dblValue.setChecked(clearDouble)
383
- self.dblValue.setToolTip(dblHelp)
384
- self.dblValue.clicked.connect(self._populateTree)
385
-
386
- self.optionsBox = QGridLayout()
387
- self.optionsBox.addWidget(self.wpLabel, 0, 0)
388
- self.optionsBox.addWidget(self.wpValue, 0, 1)
389
- self.optionsBox.addWidget(self.dblLabel, 0, 3)
390
- self.optionsBox.addWidget(self.dblValue, 0, 4)
391
- self.optionsBox.addWidget(self.poLabel, 1, 0)
392
- self.optionsBox.addWidget(self.poValue, 1, 1)
393
- self.optionsBox.setHorizontalSpacing(hPx)
394
- self.optionsBox.setVerticalSpacing(vPx)
395
- self.optionsBox.setColumnStretch(2, 1)
396
-
397
- # Assemble
398
- # ========
399
-
400
- self.outerBox = QVBoxLayout()
401
- self.outerBox.addLayout(self.headBox)
402
- self.outerBox.addWidget(self.tocTree)
403
- self.outerBox.addLayout(self.optionsBox)
404
-
405
- self.setLayout(self.outerBox)
406
-
407
- return
408
-
409
- def getColumnSizes(self):
410
- """Return the column widths for the tree columns.
411
- """
412
- retVals = [
413
- self.tocTree.columnWidth(0),
414
- self.tocTree.columnWidth(1),
415
- self.tocTree.columnWidth(2),
416
- self.tocTree.columnWidth(3),
417
- self.tocTree.columnWidth(4),
418
- ]
419
- return retVals
420
-
421
- def updateValues(self):
422
- """Populate the tree.
423
- """
424
- self._currentRoot = None
425
- self.novelValue.updateList()
426
- self.novelValue.setHandle(self.novelValue.firstHandle)
427
- self._prepareData(self.novelValue.firstHandle)
428
- self._populateTree()
429
-
430
- return
431
-
432
- ##
433
- # Internal Functions
434
- ##
435
-
436
- def _prepareData(self, rootHandle):
437
- """Extract the information from the project index.
438
- """
439
- logger.debug("Populating ToC from handle '%s'", rootHandle)
440
- self._theToC = SHARED.project.index.getTableOfContents(rootHandle, 2)
441
- self._theToC.append(("", 0, self.tr("END"), 0))
442
- return
443
-
444
- ##
445
- # Slots
446
- ##
447
-
448
- @pyqtSlot(str)
449
- def _novelValueChanged(self, tHandle):
450
- """Refresh the tree with another root item.
451
- """
452
- if tHandle != self._currentRoot:
453
- self._prepareData(tHandle)
454
- self._populateTree()
455
- self._currentRoot = self.novelValue.handle
456
- return
457
-
458
- @pyqtSlot()
459
- def _populateTree(self):
460
- """Set the content of the chapter/page tree.
461
- """
462
- dblPages = self.dblValue.isChecked()
463
- wpPage = self.wpValue.value()
464
- fstPage = self.poValue.value() - 1
465
-
466
- pTotal = 0
467
- tPages = 1
468
-
469
- theList = []
470
- for _, tLevel, tTitle, wCount in self._theToC:
471
- pCount = math.ceil(wCount/wpPage)
472
- if dblPages:
473
- pCount += pCount%2
474
-
475
- pTotal += pCount
476
- theList.append((tLevel, tTitle, wCount, pCount))
477
-
478
- pMax = pTotal - fstPage
479
-
480
- self.tocTree.clear()
481
- for tLevel, tTitle, wCount, pCount in theList:
482
- newItem = QTreeWidgetItem()
483
-
484
- if tPages <= fstPage:
485
- progPage = numberToRoman(tPages, True)
486
- progText = ""
487
- else:
488
- cPage = tPages - fstPage
489
- pgProg = 100.0*(cPage - 1)/pMax if pMax > 0 else 0.0
490
- progPage = f"{cPage:n}"
491
- progText = f"{pgProg:.1f}{nwUnicode.U_THSP}%"
492
-
493
- hDec = SHARED.theme.getHeaderDecoration(tLevel)
494
- if tTitle.strip() == "":
495
- tTitle = self.tr("Untitled")
496
-
497
- newItem.setData(self.C_TITLE, Qt.DecorationRole, hDec)
498
- newItem.setText(self.C_TITLE, tTitle)
499
- newItem.setText(self.C_WORDS, f"{wCount:n}")
500
- newItem.setText(self.C_PAGES, f"{pCount:n}")
501
- newItem.setText(self.C_PAGE, progPage)
502
- newItem.setText(self.C_PROG, progText)
503
-
504
- newItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
505
- newItem.setTextAlignment(self.C_PAGES, Qt.AlignRight)
506
- newItem.setTextAlignment(self.C_PAGE, Qt.AlignRight)
507
- newItem.setTextAlignment(self.C_PROG, Qt.AlignRight)
508
-
509
- # Make pages and titles/partitions stand out
510
- if tLevel < 2:
511
- bFont = newItem.font(self.C_TITLE)
512
- if tLevel == 0:
513
- bFont.setItalic(True)
514
- else:
515
- bFont.setBold(True)
516
- bFont.setUnderline(True)
517
- newItem.setFont(self.C_TITLE, bFont)
518
-
519
- tPages += pCount
520
-
521
- self.tocTree.addTopLevelItem(newItem)
522
-
523
- return
524
-
525
- # END Class GuiProjectDetailsContents