novelWriter 2.1.1__py3-none-any.whl → 2.2rc1__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.
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/METADATA +3 -3
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/RECORD +105 -76
- novelwriter/__init__.py +6 -24
- novelwriter/assets/i18n/project_de_DE.json +10 -0
- novelwriter/assets/i18n/project_en_GB.json +11 -0
- novelwriter/assets/i18n/project_en_US.json +10 -0
- novelwriter/assets/i18n/project_ja_JP.json +11 -1
- novelwriter/assets/i18n/project_nb_NO.json +10 -0
- novelwriter/assets/i18n/project_nn_NO.json +10 -0
- novelwriter/assets/icons/novelwriter.ico +0 -0
- novelwriter/assets/icons/novelwriter.svg +8 -183
- novelwriter/assets/icons/typicons_dark/icons.conf +17 -2
- novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_panel.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +8 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +8 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +5 -0
- novelwriter/assets/icons/typicons_dark/typ_eye.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +17 -2
- novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_panel.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +8 -0
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +8 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +5 -0
- novelwriter/assets/icons/typicons_light/typ_eye.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +4 -0
- novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- novelwriter/assets/icons/x-novelwriter-project.svg +7 -206
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +7 -0
- novelwriter/assets/text/release_notes.htm +7 -37
- novelwriter/common.py +22 -1
- novelwriter/config.py +27 -42
- novelwriter/constants.py +45 -7
- novelwriter/core/buildsettings.py +40 -24
- novelwriter/core/coretools.py +8 -1
- novelwriter/core/docbuild.py +2 -6
- novelwriter/core/index.py +264 -175
- novelwriter/core/options.py +8 -3
- novelwriter/core/project.py +2 -2
- novelwriter/core/projectdata.py +3 -3
- novelwriter/core/tohtml.py +60 -59
- novelwriter/core/tokenizer.py +110 -70
- novelwriter/core/tomd.py +51 -38
- novelwriter/core/toodt.py +184 -147
- novelwriter/dialogs/preferences.py +75 -106
- novelwriter/dialogs/projsettings.py +101 -110
- novelwriter/dialogs/updates.py +25 -14
- novelwriter/enum.py +28 -3
- novelwriter/extensions/novelselector.py +1 -1
- novelwriter/gui/doceditor.py +1345 -1235
- novelwriter/gui/dochighlight.py +98 -62
- novelwriter/gui/docviewer.py +151 -340
- novelwriter/gui/docviewerpanel.py +457 -0
- novelwriter/gui/editordocument.py +126 -0
- novelwriter/gui/mainmenu.py +350 -300
- novelwriter/gui/noveltree.py +101 -125
- novelwriter/gui/outline.py +154 -171
- novelwriter/gui/projtree.py +480 -380
- novelwriter/gui/sidebar.py +106 -75
- novelwriter/gui/statusbar.py +1 -1
- novelwriter/gui/theme.py +114 -75
- novelwriter/guimain.py +353 -254
- novelwriter/shared.py +36 -3
- novelwriter/tools/dictionaries.py +268 -0
- novelwriter/tools/manusbuild.py +17 -6
- novelwriter/tools/manuscript.py +11 -3
- novelwriter/tools/manussettings.py +0 -14
- novelwriter/tools/projwizard.py +16 -2
- novelwriter/tools/writingstats.py +1 -1
- novelwriter/assets/icons/typicons_dark/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-menu.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-menu.svg +0 -4
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/WHEEL +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.1.1.dist-info → novelWriter-2.2rc1.dist-info}/top_level.txt +0 -0
novelwriter/gui/outline.py
CHANGED
@@ -59,8 +59,8 @@ class GuiOutlineView(QWidget):
|
|
59
59
|
loadDocumentTagRequest = pyqtSignal(str, Enum)
|
60
60
|
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
61
61
|
|
62
|
-
def __init__(self,
|
63
|
-
super().__init__(parent=
|
62
|
+
def __init__(self, parent: QWidget) -> None:
|
63
|
+
super().__init__(parent=parent)
|
64
64
|
|
65
65
|
# Build GUI
|
66
66
|
self.outlineTree = GuiOutlineTree(self)
|
@@ -98,38 +98,33 @@ class GuiOutlineView(QWidget):
|
|
98
98
|
# Methods
|
99
99
|
##
|
100
100
|
|
101
|
-
def updateTheme(self):
|
102
|
-
"""Update theme elements.
|
103
|
-
"""
|
101
|
+
def updateTheme(self) -> None:
|
102
|
+
"""Update theme elements."""
|
104
103
|
self.outlineBar.updateTheme()
|
105
104
|
self.refreshTree()
|
106
105
|
return
|
107
106
|
|
108
|
-
def initSettings(self):
|
109
|
-
"""Initialise GUI elements that depend on specific settings.
|
110
|
-
"""
|
107
|
+
def initSettings(self) -> None:
|
108
|
+
"""Initialise GUI elements that depend on specific settings."""
|
111
109
|
self.outlineTree.initSettings()
|
112
110
|
self.outlineData.initSettings()
|
113
111
|
return
|
114
112
|
|
115
|
-
def refreshTree(self):
|
116
|
-
"""Refresh the current tree.
|
117
|
-
"""
|
113
|
+
def refreshTree(self) -> None:
|
114
|
+
"""Refresh the current tree."""
|
118
115
|
self.outlineTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("outline"))
|
119
116
|
return
|
120
117
|
|
121
|
-
def clearOutline(self):
|
122
|
-
"""Clear project-related GUI content.
|
123
|
-
"""
|
118
|
+
def clearOutline(self) -> None:
|
119
|
+
"""Clear project-related GUI content."""
|
124
120
|
self.outlineData.clearDetails()
|
125
121
|
self.outlineBar.setEnabled(False)
|
126
122
|
return
|
127
123
|
|
128
|
-
def openProjectTasks(self):
|
129
|
-
"""Run open project tasks.
|
130
|
-
"""
|
124
|
+
def openProjectTasks(self) -> None:
|
125
|
+
"""Run open project tasks."""
|
131
126
|
lastOutline = SHARED.project.data.getLastHandle("outline")
|
132
|
-
if not (lastOutline in SHARED.project.tree
|
127
|
+
if not (lastOutline is None or lastOutline in SHARED.project.tree):
|
133
128
|
lastOutline = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
134
129
|
|
135
130
|
logger.debug("Setting outline tree to root item '%s'", lastOutline)
|
@@ -141,23 +136,23 @@ class GuiOutlineView(QWidget):
|
|
141
136
|
|
142
137
|
return
|
143
138
|
|
144
|
-
def closeProjectTasks(self):
|
139
|
+
def closeProjectTasks(self) -> None:
|
140
|
+
"""Run closing project tasks."""
|
145
141
|
self.outlineTree.closeProjectTasks()
|
146
142
|
self.outlineData.updateClasses()
|
147
143
|
self.clearOutline()
|
148
144
|
return
|
149
145
|
|
150
|
-
def splitSizes(self):
|
146
|
+
def splitSizes(self) -> list[int]:
|
147
|
+
"""Get the sizes of the splitter widget."""
|
151
148
|
return self.splitOutline.sizes()
|
152
149
|
|
153
|
-
def setTreeFocus(self):
|
154
|
-
"""Set the focus to the tree widget.
|
155
|
-
"""
|
150
|
+
def setTreeFocus(self) -> None:
|
151
|
+
"""Set the focus to the tree widget."""
|
156
152
|
return self.outlineTree.setFocus()
|
157
153
|
|
158
|
-
def treeHasFocus(self):
|
159
|
-
"""Check if the outline tree has focus.
|
160
|
-
"""
|
154
|
+
def treeHasFocus(self) -> bool:
|
155
|
+
"""Check if the outline tree has focus."""
|
161
156
|
return self.outlineTree.hasFocus()
|
162
157
|
|
163
158
|
##
|
@@ -165,9 +160,8 @@ class GuiOutlineView(QWidget):
|
|
165
160
|
##
|
166
161
|
|
167
162
|
@pyqtSlot(str)
|
168
|
-
def updateRootItem(self, tHandle):
|
169
|
-
"""
|
170
|
-
"""
|
163
|
+
def updateRootItem(self, tHandle: str) -> None:
|
164
|
+
"""Handle tasks whenever a root folders changes."""
|
171
165
|
self.outlineBar.populateNovelList()
|
172
166
|
self.outlineData.updateClasses()
|
173
167
|
return
|
@@ -177,7 +171,7 @@ class GuiOutlineView(QWidget):
|
|
177
171
|
##
|
178
172
|
|
179
173
|
@pyqtSlot()
|
180
|
-
def _updateMenuColumns(self):
|
174
|
+
def _updateMenuColumns(self) -> None:
|
181
175
|
"""Trigger an update of the toggled state of the column menu
|
182
176
|
checkboxes whenever a signal is received that the hidden state
|
183
177
|
of columns has changed.
|
@@ -186,18 +180,16 @@ class GuiOutlineView(QWidget):
|
|
186
180
|
return
|
187
181
|
|
188
182
|
@pyqtSlot(str)
|
189
|
-
def _tagClicked(self, link):
|
190
|
-
"""Capture the click of a tag in the details panel.
|
191
|
-
"""
|
183
|
+
def _tagClicked(self, link: str) -> None:
|
184
|
+
"""Capture the click of a tag in the details panel."""
|
192
185
|
if link:
|
193
186
|
self.loadDocumentTagRequest.emit(link, nwDocMode.VIEW)
|
194
187
|
return
|
195
188
|
|
196
189
|
@pyqtSlot(str)
|
197
|
-
def _rootItemChanged(self,
|
198
|
-
"""
|
199
|
-
|
200
|
-
self.outlineTree.refreshTree(rootHandle=(handle or None), overRide=True)
|
190
|
+
def _rootItemChanged(self, tHandle) -> None:
|
191
|
+
"""Handle root novel changed or needs to be refreshed."""
|
192
|
+
self.outlineTree.refreshTree(rootHandle=(tHandle or None), overRide=True)
|
201
193
|
return
|
202
194
|
|
203
195
|
# END Class GuiOutlineView
|
@@ -208,8 +200,8 @@ class GuiOutlineToolBar(QToolBar):
|
|
208
200
|
loadNovelRootRequest = pyqtSignal(str)
|
209
201
|
viewColumnToggled = pyqtSignal(bool, Enum)
|
210
202
|
|
211
|
-
def __init__(self,
|
212
|
-
super().__init__(parent=
|
203
|
+
def __init__(self, outlineView: GuiOutlineView) -> None:
|
204
|
+
super().__init__(parent=outlineView)
|
213
205
|
|
214
206
|
logger.debug("Create: GuiOutlineToolBar")
|
215
207
|
|
@@ -221,7 +213,7 @@ class GuiOutlineToolBar(QToolBar):
|
|
221
213
|
self.setContentsMargins(0, 0, 0, 0)
|
222
214
|
|
223
215
|
stretch = QWidget(self)
|
224
|
-
stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
216
|
+
stretch.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
225
217
|
|
226
218
|
# Novel Selector
|
227
219
|
self.novelLabel = QLabel(self.tr("Outline of"))
|
@@ -243,7 +235,7 @@ class GuiOutlineToolBar(QToolBar):
|
|
243
235
|
|
244
236
|
self.tbColumns = QToolButton(self)
|
245
237
|
self.tbColumns.setMenu(self.mColumns)
|
246
|
-
self.tbColumns.setPopupMode(QToolButton.InstantPopup)
|
238
|
+
self.tbColumns.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
247
239
|
|
248
240
|
# Assemble
|
249
241
|
self.addWidget(self.novelLabel)
|
@@ -263,32 +255,27 @@ class GuiOutlineToolBar(QToolBar):
|
|
263
255
|
# Methods
|
264
256
|
##
|
265
257
|
|
266
|
-
def updateTheme(self):
|
267
|
-
"""Update theme elements.
|
268
|
-
"""
|
258
|
+
def updateTheme(self) -> None:
|
259
|
+
"""Update theme elements."""
|
269
260
|
self.setStyleSheet("QToolBar {border: 0px;}")
|
270
|
-
|
271
261
|
self.novelValue.updateList(includeAll=True)
|
272
262
|
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
|
273
263
|
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
|
274
|
-
|
264
|
+
self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
|
275
265
|
return
|
276
266
|
|
277
|
-
def populateNovelList(self):
|
278
|
-
"""Reload the content of the novel list.
|
279
|
-
"""
|
267
|
+
def populateNovelList(self) -> None:
|
268
|
+
"""Reload the content of the novel list."""
|
280
269
|
self.novelValue.updateList(includeAll=True)
|
281
270
|
return
|
282
271
|
|
283
|
-
def setCurrentRoot(self, rootHandle):
|
284
|
-
"""Set the current active root handle.
|
285
|
-
"""
|
272
|
+
def setCurrentRoot(self, rootHandle: str | None) -> None:
|
273
|
+
"""Set the current active root handle."""
|
286
274
|
self.novelValue.setHandle(rootHandle)
|
287
275
|
return
|
288
276
|
|
289
|
-
def setColumnHiddenState(self, hiddenState):
|
290
|
-
"""Forward the change of column hidden states to the menu.
|
291
|
-
"""
|
277
|
+
def setColumnHiddenState(self, hiddenState: dict[nwOutline, bool]) -> None:
|
278
|
+
"""Forward the change of column hidden states to the menu."""
|
292
279
|
self.mColumns.setHiddenState(hiddenState)
|
293
280
|
return
|
294
281
|
|
@@ -297,16 +284,14 @@ class GuiOutlineToolBar(QToolBar):
|
|
297
284
|
##
|
298
285
|
|
299
286
|
@pyqtSlot(str)
|
300
|
-
def _novelValueChanged(self, tHandle):
|
301
|
-
"""Emit a signal containing the handle of the selected item.
|
302
|
-
"""
|
287
|
+
def _novelValueChanged(self, tHandle: str) -> None:
|
288
|
+
"""Emit a signal containing the handle of the selected item."""
|
303
289
|
self.loadNovelRootRequest.emit(tHandle)
|
304
290
|
return
|
305
291
|
|
306
292
|
@pyqtSlot()
|
307
|
-
def _refreshRequested(self):
|
308
|
-
"""Emit a signal containing the handle of the selected item.
|
309
|
-
"""
|
293
|
+
def _refreshRequested(self) -> None:
|
294
|
+
"""Emit a signal containing the handle of the selected item."""
|
310
295
|
self.loadNovelRootRequest.emit(self.novelValue.handle)
|
311
296
|
return
|
312
297
|
|
@@ -361,7 +346,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
361
346
|
hiddenStateChanged = pyqtSignal()
|
362
347
|
activeItemChanged = pyqtSignal(str, str)
|
363
348
|
|
364
|
-
def __init__(self, outlineView):
|
349
|
+
def __init__(self, outlineView: GuiOutlineView) -> None:
|
365
350
|
super().__init__(parent=outlineView)
|
366
351
|
|
367
352
|
logger.debug("Create: GuiOutlineTree")
|
@@ -369,9 +354,9 @@ class GuiOutlineTree(QTreeWidget):
|
|
369
354
|
self.outlineView = outlineView
|
370
355
|
|
371
356
|
self.setUniformRowHeights(True)
|
372
|
-
self.setFrameStyle(QFrame.NoFrame)
|
373
|
-
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
374
|
-
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
357
|
+
self.setFrameStyle(QFrame.Shape.NoFrame)
|
358
|
+
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
359
|
+
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
375
360
|
self.setExpandsOnDoubleClick(False)
|
376
361
|
self.setDragEnabled(False)
|
377
362
|
self.itemDoubleClicked.connect(self._treeDoubleClick)
|
@@ -392,13 +377,17 @@ class GuiOutlineTree(QTreeWidget):
|
|
392
377
|
fH2 = self.font()
|
393
378
|
fH2.setBold(True)
|
394
379
|
|
380
|
+
iType = nwItemType.FILE
|
381
|
+
iClass = nwItemClass.NO_CLASS
|
382
|
+
iLayout = nwItemLayout.DOCUMENT
|
383
|
+
|
395
384
|
self._hFonts = [self.font(), fH1, fH2, self.font(), self.font()]
|
396
385
|
self._dIcon = {
|
397
|
-
"H0": SHARED.theme.getItemIcon(
|
398
|
-
"H1": SHARED.theme.getItemIcon(
|
399
|
-
"H2": SHARED.theme.getItemIcon(
|
400
|
-
"H3": SHARED.theme.getItemIcon(
|
401
|
-
"H4": SHARED.theme.getItemIcon(
|
386
|
+
"H0": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H0"),
|
387
|
+
"H1": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H1"),
|
388
|
+
"H2": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H2"),
|
389
|
+
"H3": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H3"),
|
390
|
+
"H4": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H4"),
|
402
391
|
}
|
403
392
|
|
404
393
|
# Internals
|
@@ -431,23 +420,19 @@ class GuiOutlineTree(QTreeWidget):
|
|
431
420
|
# Methods
|
432
421
|
##
|
433
422
|
|
434
|
-
def initSettings(self):
|
435
|
-
"""Set or update outline settings.
|
436
|
-
"""
|
437
|
-
# Scroll bars
|
423
|
+
def initSettings(self) -> None:
|
424
|
+
"""Set or update outline settings."""
|
438
425
|
if CONFIG.hideVScroll:
|
439
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
426
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
440
427
|
else:
|
441
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
442
|
-
|
428
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
443
429
|
if CONFIG.hideHScroll:
|
444
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
430
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
445
431
|
else:
|
446
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
447
|
-
|
432
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
448
433
|
return
|
449
434
|
|
450
|
-
def clearContent(self):
|
435
|
+
def clearContent(self) -> None:
|
451
436
|
"""Clear the tree and header and set the default values for the
|
452
437
|
columns arrays.
|
453
438
|
"""
|
@@ -455,10 +440,10 @@ class GuiOutlineTree(QTreeWidget):
|
|
455
440
|
self.setColumnCount(1)
|
456
441
|
self.setHeaderLabel(trConst(nwLabels.OUTLINE_COLS[nwOutline.TITLE]))
|
457
442
|
|
458
|
-
self._treeOrder = []
|
459
|
-
self._colWidth = {}
|
460
|
-
self._colHidden = {}
|
461
|
-
self._colIdx = {}
|
443
|
+
self._treeOrder: list[nwOutline] = []
|
444
|
+
self._colWidth: dict[nwOutline, int] = {}
|
445
|
+
self._colHidden: dict[nwOutline, bool] = {}
|
446
|
+
self._colIdx: dict[nwOutline, int] = {}
|
462
447
|
self._treeNCols = 0
|
463
448
|
|
464
449
|
for hItem in nwOutline:
|
@@ -470,7 +455,8 @@ class GuiOutlineTree(QTreeWidget):
|
|
470
455
|
|
471
456
|
return
|
472
457
|
|
473
|
-
def refreshTree(self, rootHandle
|
458
|
+
def refreshTree(self, rootHandle: str | None = None,
|
459
|
+
overRide: bool = False, novelChanged: bool = False) -> None:
|
474
460
|
"""Called whenever the Outline tab is activated and controls
|
475
461
|
what data to load, and if necessary, force a rebuild of the
|
476
462
|
tree.
|
@@ -494,15 +480,14 @@ class GuiOutlineTree(QTreeWidget):
|
|
494
480
|
|
495
481
|
return
|
496
482
|
|
497
|
-
def closeProjectTasks(self):
|
498
|
-
"""Called before a project is closed.
|
499
|
-
"""
|
483
|
+
def closeProjectTasks(self) -> None:
|
484
|
+
"""Called before a project is closed."""
|
500
485
|
self._saveHeaderState()
|
501
486
|
self.clearContent()
|
502
487
|
self._firstView = True
|
503
488
|
return
|
504
489
|
|
505
|
-
def getSelectedHandle(self):
|
490
|
+
def getSelectedHandle(self) -> tuple[str | None, str | None]:
|
506
491
|
"""Get the currently selected handle. If multiple items are
|
507
492
|
selected, return the first.
|
508
493
|
"""
|
@@ -518,7 +503,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
518
503
|
##
|
519
504
|
|
520
505
|
@pyqtSlot("QTreeWidgetItem*", int)
|
521
|
-
def _treeDoubleClick(self, tItem, tCol):
|
506
|
+
def _treeDoubleClick(self, tItem: QTreeWidgetItem, tCol: int) -> None:
|
522
507
|
"""Extract the handle and line number of the title double-
|
523
508
|
clicked, and send it to the main gui class for opening in the
|
524
509
|
document editor.
|
@@ -530,7 +515,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
530
515
|
return
|
531
516
|
|
532
517
|
@pyqtSlot()
|
533
|
-
def _itemSelected(self):
|
518
|
+
def _itemSelected(self) -> None:
|
534
519
|
"""Extract the handle and line number of the currently selected
|
535
520
|
title, and send it to the details panel.
|
536
521
|
"""
|
@@ -542,7 +527,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
542
527
|
return
|
543
528
|
|
544
529
|
@pyqtSlot(int, int, int)
|
545
|
-
def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx):
|
530
|
+
def _columnMoved(self, logIdx: int, oldVisualIdx: int, newVisualIdx: int) -> None:
|
546
531
|
"""Make sure the order array is up to date with the actual order
|
547
532
|
of the columns.
|
548
533
|
"""
|
@@ -551,12 +536,12 @@ class GuiOutlineTree(QTreeWidget):
|
|
551
536
|
return
|
552
537
|
|
553
538
|
@pyqtSlot(bool, Enum)
|
554
|
-
def menuColumnToggled(self, isChecked,
|
539
|
+
def menuColumnToggled(self, isChecked: bool, hItem: nwOutline) -> None:
|
555
540
|
"""Receive the changes to column visibility forwarded by the
|
556
541
|
column selection menu.
|
557
542
|
"""
|
558
|
-
if
|
559
|
-
self.setColumnHidden(self._colIdx[
|
543
|
+
if hItem in self._colIdx:
|
544
|
+
self.setColumnHidden(self._colIdx[hItem], not isChecked)
|
560
545
|
self._saveHeaderState()
|
561
546
|
return
|
562
547
|
|
@@ -568,7 +553,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
568
553
|
"""Load the state of the main tree header, that is, column order
|
569
554
|
and column width.
|
570
555
|
"""
|
571
|
-
# Load whatever we saved last time, regardless of
|
556
|
+
# Load whatever we saved last time, regardless of whether it
|
572
557
|
# contains the correct names or number of columns.
|
573
558
|
colState = SHARED.project.options.getValue("GuiOutline", "columnState", {})
|
574
559
|
|
@@ -600,7 +585,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
600
585
|
|
601
586
|
return
|
602
587
|
|
603
|
-
def _saveHeaderState(self):
|
588
|
+
def _saveHeaderState(self) -> None:
|
604
589
|
"""Save the state of the main tree header, that is, column
|
605
590
|
order, column width and column hidden state. We don't want to
|
606
591
|
save the current width of hidden columns though. This preserves
|
@@ -627,7 +612,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
627
612
|
|
628
613
|
return
|
629
614
|
|
630
|
-
def _populateTree(self, rootHandle):
|
615
|
+
def _populateTree(self, rootHandle: str | None) -> None:
|
631
616
|
"""Build the tree based on the project index, and the header
|
632
617
|
based on the defined constants, default values and user selected
|
633
618
|
width, order and hidden state. All columns are populated, even
|
@@ -653,22 +638,25 @@ class GuiOutlineTree(QTreeWidget):
|
|
653
638
|
|
654
639
|
headItem = self.headerItem()
|
655
640
|
if isinstance(headItem, QTreeWidgetItem):
|
656
|
-
headItem.setTextAlignment(
|
657
|
-
|
658
|
-
headItem.setTextAlignment(
|
641
|
+
headItem.setTextAlignment(
|
642
|
+
self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
|
643
|
+
headItem.setTextAlignment(
|
644
|
+
self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
|
645
|
+
headItem.setTextAlignment(
|
646
|
+
self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
|
659
647
|
|
660
648
|
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, skipExcl=True)
|
661
649
|
for _, tHandle, sTitle, novIdx in novStruct:
|
662
650
|
|
663
651
|
iLevel = nwHeaders.H_LEVEL.get(novIdx.level, 0)
|
664
|
-
|
652
|
+
nwItem = SHARED.project.tree[tHandle]
|
653
|
+
if iLevel == 0 or nwItem is None:
|
665
654
|
continue
|
666
655
|
|
667
656
|
trItem = QTreeWidgetItem()
|
668
|
-
nwItem = SHARED.project.tree[tHandle]
|
669
657
|
hDec = SHARED.theme.getHeaderDecoration(iLevel)
|
670
658
|
|
671
|
-
trItem.setData(self._colIdx[nwOutline.TITLE], Qt.DecorationRole, hDec)
|
659
|
+
trItem.setData(self._colIdx[nwOutline.TITLE], Qt.ItemDataRole.DecorationRole, hDec)
|
672
660
|
trItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title)
|
673
661
|
trItem.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle)
|
674
662
|
trItem.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle)
|
@@ -681,9 +669,9 @@ class GuiOutlineTree(QTreeWidget):
|
|
681
669
|
trItem.setText(self._colIdx[nwOutline.CCOUNT], f"{novIdx.charCount:n}")
|
682
670
|
trItem.setText(self._colIdx[nwOutline.WCOUNT], f"{novIdx.wordCount:n}")
|
683
671
|
trItem.setText(self._colIdx[nwOutline.PCOUNT], f"{novIdx.paraCount:n}")
|
684
|
-
trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignRight)
|
685
|
-
trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight)
|
686
|
-
trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight)
|
672
|
+
trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
|
673
|
+
trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
|
674
|
+
trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
|
687
675
|
|
688
676
|
refs = SHARED.project.index.getReferences(tHandle, sTitle)
|
689
677
|
trItem.setText(self._colIdx[nwOutline.POV], ", ".join(refs[nwKeyWords.POV_KEY]))
|
@@ -709,8 +697,8 @@ class GuiOutlineHeaderMenu(QMenu):
|
|
709
697
|
|
710
698
|
columnToggled = pyqtSignal(bool, Enum)
|
711
699
|
|
712
|
-
def __init__(self,
|
713
|
-
super().__init__(parent=
|
700
|
+
def __init__(self, outlineToolBar: GuiOutlineToolBar) -> None:
|
701
|
+
super().__init__(parent=outlineToolBar)
|
714
702
|
|
715
703
|
self.acceptToggle = True
|
716
704
|
|
@@ -731,7 +719,7 @@ class GuiOutlineHeaderMenu(QMenu):
|
|
731
719
|
|
732
720
|
return
|
733
721
|
|
734
|
-
def setHiddenState(self, hiddenState):
|
722
|
+
def setHiddenState(self, hiddenState: dict[nwOutline, bool]) -> None:
|
735
723
|
"""Overwrite the checked state of the columns as the inverse of
|
736
724
|
the hidden state. Skip the TITLE column as it cannot be hidden.
|
737
725
|
"""
|
@@ -760,12 +748,12 @@ class GuiOutlineDetails(QScrollArea):
|
|
760
748
|
|
761
749
|
itemTagClicked = pyqtSignal(str)
|
762
750
|
|
763
|
-
def __init__(self,
|
764
|
-
super().__init__(parent=
|
751
|
+
def __init__(self, outlineView: GuiOutlineView) -> None:
|
752
|
+
super().__init__(parent=outlineView)
|
765
753
|
|
766
754
|
logger.debug("Create: GuiOutlineDetails")
|
767
755
|
|
768
|
-
self.
|
756
|
+
self.outlineView = outlineView
|
769
757
|
|
770
758
|
# Sizes
|
771
759
|
minTitle = 30*SHARED.theme.textNWidth
|
@@ -878,23 +866,26 @@ class GuiOutlineDetails(QScrollArea):
|
|
878
866
|
|
879
867
|
# Selected Item Details
|
880
868
|
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
881
|
-
self.mainForm
|
869
|
+
self.mainForm = QGridLayout()
|
882
870
|
self.mainGroup.setLayout(self.mainForm)
|
883
871
|
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
self.mainForm.addWidget(self.
|
888
|
-
self.mainForm.addWidget(self.
|
889
|
-
self.mainForm.addWidget(self.
|
890
|
-
self.mainForm.addWidget(self.
|
891
|
-
self.mainForm.addWidget(self.
|
892
|
-
self.mainForm.addWidget(self.
|
893
|
-
self.mainForm.addWidget(self.
|
894
|
-
self.mainForm.addWidget(self.
|
895
|
-
self.mainForm.addWidget(self.
|
896
|
-
self.mainForm.addWidget(self.
|
897
|
-
self.mainForm.
|
872
|
+
topLeft = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft
|
873
|
+
topRight = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight
|
874
|
+
|
875
|
+
self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, topLeft)
|
876
|
+
self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, topLeft)
|
877
|
+
self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, topLeft)
|
878
|
+
self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, topRight)
|
879
|
+
self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, topLeft)
|
880
|
+
self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, topLeft)
|
881
|
+
self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, topLeft)
|
882
|
+
self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, topRight)
|
883
|
+
self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, topLeft)
|
884
|
+
self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, topLeft)
|
885
|
+
self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, topLeft)
|
886
|
+
self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, topRight)
|
887
|
+
self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, topLeft)
|
888
|
+
self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, topLeft)
|
898
889
|
|
899
890
|
self.mainForm.setColumnStretch(1, 1)
|
900
891
|
self.mainForm.setRowStretch(4, 1)
|
@@ -906,24 +897,24 @@ class GuiOutlineDetails(QScrollArea):
|
|
906
897
|
self.tagsForm = QGridLayout()
|
907
898
|
self.tagsGroup.setLayout(self.tagsForm)
|
908
899
|
|
909
|
-
self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1,
|
910
|
-
self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1,
|
911
|
-
self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1,
|
912
|
-
self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1,
|
913
|
-
self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1,
|
914
|
-
self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1,
|
915
|
-
self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1,
|
916
|
-
self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1,
|
917
|
-
self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1,
|
918
|
-
self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1,
|
919
|
-
self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1,
|
920
|
-
self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1,
|
921
|
-
self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1,
|
922
|
-
self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1,
|
923
|
-
self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1,
|
924
|
-
self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1,
|
925
|
-
self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1,
|
926
|
-
self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1,
|
900
|
+
self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, topLeft)
|
901
|
+
self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, topLeft)
|
902
|
+
self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, topLeft)
|
903
|
+
self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, topLeft)
|
904
|
+
self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, topLeft)
|
905
|
+
self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, topLeft)
|
906
|
+
self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, topLeft)
|
907
|
+
self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, topLeft)
|
908
|
+
self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, topLeft)
|
909
|
+
self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, topLeft)
|
910
|
+
self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, topLeft)
|
911
|
+
self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, topLeft)
|
912
|
+
self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, topLeft)
|
913
|
+
self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, topLeft)
|
914
|
+
self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, topLeft)
|
915
|
+
self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, topLeft)
|
916
|
+
self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, topLeft)
|
917
|
+
self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, topLeft)
|
927
918
|
|
928
919
|
self.tagsForm.setColumnStretch(1, 1)
|
929
920
|
self.tagsForm.setRowStretch(8, 1)
|
@@ -939,10 +930,10 @@ class GuiOutlineDetails(QScrollArea):
|
|
939
930
|
self.outerWidget.setLayout(self.outerBox)
|
940
931
|
self.setWidget(self.outerWidget)
|
941
932
|
|
942
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
943
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
933
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
934
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
944
935
|
self.setWidgetResizable(True)
|
945
|
-
self.setFrameStyle(QFrame.NoFrame)
|
936
|
+
self.setFrameStyle(QFrame.Shape.NoFrame)
|
946
937
|
|
947
938
|
self.initSettings()
|
948
939
|
|
@@ -950,27 +941,21 @@ class GuiOutlineDetails(QScrollArea):
|
|
950
941
|
|
951
942
|
return
|
952
943
|
|
953
|
-
def initSettings(self):
|
954
|
-
"""Set or update outline settings.
|
955
|
-
"""
|
956
|
-
# Scroll bars
|
944
|
+
def initSettings(self) -> None:
|
945
|
+
"""Set or update outline settings."""
|
957
946
|
if CONFIG.hideVScroll:
|
958
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
947
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
959
948
|
else:
|
960
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
961
|
-
|
949
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
962
950
|
if CONFIG.hideHScroll:
|
963
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
951
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
964
952
|
else:
|
965
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
966
|
-
|
953
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
967
954
|
self.updateClasses()
|
968
|
-
|
969
955
|
return
|
970
956
|
|
971
|
-
def clearDetails(self):
|
972
|
-
"""Clear all the data labels.
|
973
|
-
"""
|
957
|
+
def clearDetails(self) -> None:
|
958
|
+
"""Clear all the data labels."""
|
974
959
|
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
975
960
|
self.titleValue.setText("")
|
976
961
|
self.fileValue.setText("")
|
@@ -996,7 +981,7 @@ class GuiOutlineDetails(QScrollArea):
|
|
996
981
|
##
|
997
982
|
|
998
983
|
@pyqtSlot(str, str)
|
999
|
-
def showItem(self, tHandle, sTitle):
|
984
|
+
def showItem(self, tHandle: str, sTitle: str) -> bool:
|
1000
985
|
"""Update the content of the tree with the given handle and line
|
1001
986
|
number pointing to a header.
|
1002
987
|
"""
|
@@ -1041,9 +1026,8 @@ class GuiOutlineDetails(QScrollArea):
|
|
1041
1026
|
return True
|
1042
1027
|
|
1043
1028
|
@pyqtSlot()
|
1044
|
-
def updateClasses(self):
|
1045
|
-
"""Update the visibility status of class details.
|
1046
|
-
"""
|
1029
|
+
def updateClasses(self) -> None:
|
1030
|
+
"""Update the visibility status of class details."""
|
1047
1031
|
usedClasses = SHARED.project.tree.rootClasses()
|
1048
1032
|
|
1049
1033
|
pltVisible = nwItemClass.PLOT in usedClasses
|
@@ -1069,9 +1053,8 @@ class GuiOutlineDetails(QScrollArea):
|
|
1069
1053
|
return
|
1070
1054
|
|
1071
1055
|
@staticmethod
|
1072
|
-
def _formatTags(refs, key):
|
1073
|
-
"""Convert a list of tags into a list of clickable tag links.
|
1074
|
-
"""
|
1056
|
+
def _formatTags(refs: dict[str, list[str]], key: str) -> str:
|
1057
|
+
"""Convert a list of tags into a list of clickable tag links."""
|
1075
1058
|
return ", ".join(
|
1076
1059
|
[f"<a href='{tag}'>{tag}</a>" for tag in refs.get(key, [])]
|
1077
1060
|
)
|