novelWriter 2.6b1__py3-none-any.whl → 2.6b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/METADATA +3 -3
  2. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/RECORD +68 -52
  3. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +49 -10
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  7. novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
  8. novelwriter/assets/i18n/project_de_DE.json +2 -2
  9. novelwriter/assets/i18n/project_ru_RU.json +11 -0
  10. novelwriter/assets/icons/typicons_dark/icons.conf +7 -0
  11. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
  12. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
  13. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
  14. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
  15. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
  16. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
  17. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
  18. novelwriter/assets/icons/typicons_light/icons.conf +7 -0
  19. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
  20. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
  21. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
  22. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
  23. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
  24. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
  25. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
  26. novelwriter/assets/manual.pdf +0 -0
  27. novelwriter/assets/sample.zip +0 -0
  28. novelwriter/assets/text/credits_en.htm +1 -0
  29. novelwriter/common.py +37 -2
  30. novelwriter/config.py +15 -12
  31. novelwriter/constants.py +24 -9
  32. novelwriter/core/coretools.py +111 -125
  33. novelwriter/core/docbuild.py +3 -2
  34. novelwriter/core/index.py +9 -19
  35. novelwriter/core/item.py +39 -6
  36. novelwriter/core/itemmodel.py +518 -0
  37. novelwriter/core/project.py +67 -89
  38. novelwriter/core/status.py +7 -5
  39. novelwriter/core/tree.py +268 -287
  40. novelwriter/dialogs/docmerge.py +7 -17
  41. novelwriter/dialogs/preferences.py +3 -3
  42. novelwriter/dialogs/projectsettings.py +2 -2
  43. novelwriter/enum.py +7 -0
  44. novelwriter/extensions/configlayout.py +6 -4
  45. novelwriter/formats/todocx.py +34 -38
  46. novelwriter/formats/tohtml.py +14 -15
  47. novelwriter/formats/tokenizer.py +21 -17
  48. novelwriter/formats/toodt.py +53 -124
  49. novelwriter/formats/toqdoc.py +92 -44
  50. novelwriter/gui/doceditor.py +230 -219
  51. novelwriter/gui/docviewer.py +38 -9
  52. novelwriter/gui/docviewerpanel.py +14 -22
  53. novelwriter/gui/itemdetails.py +17 -24
  54. novelwriter/gui/mainmenu.py +13 -8
  55. novelwriter/gui/noveltree.py +12 -12
  56. novelwriter/gui/outline.py +10 -11
  57. novelwriter/gui/projtree.py +548 -1202
  58. novelwriter/gui/search.py +9 -10
  59. novelwriter/gui/theme.py +7 -3
  60. novelwriter/guimain.py +59 -43
  61. novelwriter/shared.py +52 -23
  62. novelwriter/text/patterns.py +17 -5
  63. novelwriter/tools/manusbuild.py +13 -11
  64. novelwriter/tools/manussettings.py +42 -52
  65. novelwriter/types.py +7 -1
  66. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
  67. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
  68. {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
@@ -31,16 +31,19 @@ import logging
31
31
  from enum import Enum
32
32
 
33
33
  from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
34
- from PyQt5.QtGui import QCursor, QDesktopServices, QMouseEvent, QPalette, QResizeEvent, QTextCursor
34
+ from PyQt5.QtGui import (
35
+ QCursor, QDesktopServices, QDragEnterEvent, QDragMoveEvent, QDropEvent,
36
+ QMouseEvent, QPalette, QResizeEvent, QTextCursor
37
+ )
35
38
  from PyQt5.QtWidgets import (
36
39
  QAction, QApplication, QFrame, QHBoxLayout, QMenu, QTextBrowser,
37
40
  QToolButton, QWidget
38
41
  )
39
42
 
40
43
  from novelwriter import CONFIG, SHARED
41
- from novelwriter.common import qtLambda
42
- from novelwriter.constants import nwStyles, nwUnicode
43
- from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
44
+ from novelwriter.common import decodeMimeHandles, qtLambda
45
+ from novelwriter.constants import nwConst, nwStyles, nwUnicode
46
+ from novelwriter.enum import nwChange, nwDocAction, nwDocMode, nwItemType
44
47
  from novelwriter.error import logException
45
48
  from novelwriter.extensions.configlayout import NColourLabel
46
49
  from novelwriter.extensions.eventfilters import WheelEventFilter
@@ -216,7 +219,7 @@ class GuiDocViewer(QTextBrowser):
216
219
  qDoc = ToQTextDocument(SHARED.project)
217
220
  qDoc.setJustify(CONFIG.doJustify)
218
221
  qDoc.setDialogHighlight(True)
219
- qDoc.setFont(CONFIG.textFont)
222
+ qDoc.setTextFont(CONFIG.textFont)
220
223
  qDoc.setTheme(self._docTheme)
221
224
  qDoc.initDocument()
222
225
  qDoc.setKeywords(True)
@@ -343,10 +346,10 @@ class GuiDocViewer(QTextBrowser):
343
346
  # Public Slots
344
347
  ##
345
348
 
346
- @pyqtSlot(str)
347
- def updateDocInfo(self, tHandle: str) -> None:
349
+ @pyqtSlot(str, Enum)
350
+ def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
348
351
  """Update the header title bar if needed."""
349
- if tHandle and tHandle == self._docHandle:
352
+ if tHandle == self._docHandle and change == nwChange.UPDATE:
350
353
  self.docHeader.setHandle(tHandle)
351
354
  self.updateDocMargins()
352
355
  return
@@ -445,6 +448,32 @@ class GuiDocViewer(QTextBrowser):
445
448
  super().mouseReleaseEvent(event)
446
449
  return
447
450
 
451
+ def dragEnterEvent(self, event: QDragEnterEvent) -> None:
452
+ """Overload drag enter event to handle dragged items."""
453
+ if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
454
+ event.acceptProposedAction()
455
+ else:
456
+ super().dragEnterEvent(event)
457
+ return
458
+
459
+ def dragMoveEvent(self, event: QDragMoveEvent) -> None:
460
+ """Overload drag move event to handle dragged items."""
461
+ if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
462
+ event.acceptProposedAction()
463
+ else:
464
+ super().dragMoveEvent(event)
465
+ return
466
+
467
+ def dropEvent(self, event: QDropEvent) -> None:
468
+ """Overload drop event to handle dragged items."""
469
+ if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
470
+ if handles := decodeMimeHandles(event.mimeData()):
471
+ if SHARED.project.tree.checkType(handles[0], nwItemType.FILE):
472
+ self.openDocumentRequest.emit(handles[0], nwDocMode.VIEW, "", True)
473
+ else:
474
+ super().dropEvent(event)
475
+ return
476
+
448
477
  ##
449
478
  # Internal Functions
450
479
  ##
@@ -777,7 +806,7 @@ class GuiDocViewHeader(QWidget):
777
806
 
778
807
  if CONFIG.showFullPath:
779
808
  self.itemTitle.setText(f" {nwUnicode.U_RSAQUO} ".join(reversed(
780
- [name for name in SHARED.project.tree.getItemPath(tHandle, asName=True)]
809
+ [name for name in SHARED.project.tree.itemPath(tHandle, asName=True)]
781
810
  )))
782
811
  else:
783
812
  self.itemTitle.setText(i.itemName if (i := SHARED.project.tree[tHandle]) else "")
@@ -29,18 +29,18 @@ from enum import Enum
29
29
 
30
30
  from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, pyqtSlot
31
31
  from PyQt5.QtWidgets import (
32
- QAbstractItemView, QFrame, QHeaderView, QMenu, QTabWidget, QToolButton,
33
- QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
32
+ QAbstractItemView, QFrame, QMenu, QTabWidget, QToolButton, QTreeWidget,
33
+ QTreeWidgetItem, QVBoxLayout, QWidget
34
34
  )
35
35
 
36
36
  from novelwriter import CONFIG, SHARED
37
37
  from novelwriter.common import checkInt
38
38
  from novelwriter.constants import nwLabels, nwLists, nwStyles, trConst
39
39
  from novelwriter.core.index import IndexHeading, IndexItem
40
- from novelwriter.enum import nwDocMode, nwItemClass
40
+ from novelwriter.enum import nwChange, nwDocMode, nwItemClass
41
41
  from novelwriter.extensions.modified import NIconToolButton
42
42
  from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
43
- from novelwriter.types import QtDecoration, QtUserRole
43
+ from novelwriter.types import QtDecoration, QtHeaderFixed, QtHeaderToContents, QtUserRole
44
44
 
45
45
  logger = logging.getLogger(__name__)
46
46
 
@@ -151,8 +151,8 @@ class GuiDocViewerPanel(QWidget):
151
151
  self.updateHandle(self._lastHandle)
152
152
  return
153
153
 
154
- @pyqtSlot(str)
155
- def projectItemChanged(self, tHandle: str) -> None:
154
+ @pyqtSlot(str, Enum)
155
+ def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
156
156
  """Update meta data for project item."""
157
157
  self.tabBackRefs.refreshDocument(tHandle)
158
158
  activeOnly = self.aInactive.isChecked()
@@ -259,10 +259,10 @@ class _ViewPanelBackRefs(QTreeWidget):
259
259
  treeHeader = self.header()
260
260
  treeHeader.setStretchLastSection(True)
261
261
  treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
262
- treeHeader.setSectionResizeMode(self.C_DOC, QHeaderView.ResizeMode.ResizeToContents)
263
- treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
264
- treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
265
- treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.ResizeToContents)
262
+ treeHeader.setSectionResizeMode(self.C_DOC, QtHeaderToContents)
263
+ treeHeader.setSectionResizeMode(self.C_EDIT, QtHeaderFixed)
264
+ treeHeader.setSectionResizeMode(self.C_VIEW, QtHeaderFixed)
265
+ treeHeader.setSectionResizeMode(self.C_TITLE, QtHeaderToContents)
266
266
  treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
267
267
  treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
268
268
  treeHeader.setSectionsMovable(False)
@@ -339,17 +339,13 @@ class _ViewPanelBackRefs(QTreeWidget):
339
339
  def _setTreeItemValues(self, tHandle: str, sTitle: str, hItem: IndexHeading) -> None:
340
340
  """Add or update a tree item."""
341
341
  if nwItem := SHARED.project.tree[tHandle]:
342
- docIcon = SHARED.theme.getItemIcon(
343
- nwItem.itemType, nwItem.itemClass,
344
- nwItem.itemLayout, nwItem.mainHeading
345
- )
346
342
  iLevel = nwStyles.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
347
343
  hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
348
344
 
349
345
  tKey = f"{tHandle}:{sTitle}"
350
346
  trItem = self._treeMap[tKey] if tKey in self._treeMap else QTreeWidgetItem()
351
347
 
352
- trItem.setIcon(self.C_DOC, docIcon)
348
+ trItem.setIcon(self.C_DOC, nwItem.getMainIcon())
353
349
  trItem.setText(self.C_DOC, nwItem.itemName)
354
350
  trItem.setToolTip(self.C_DOC, nwItem.itemName)
355
351
  trItem.setIcon(self.C_EDIT, self._editIcon)
@@ -407,8 +403,8 @@ class _ViewPanelKeyWords(QTreeWidget):
407
403
  treeHeader = self.header()
408
404
  treeHeader.setStretchLastSection(True)
409
405
  treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
410
- treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
411
- treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
406
+ treeHeader.setSectionResizeMode(self.C_EDIT, QtHeaderFixed)
407
+ treeHeader.setSectionResizeMode(self.C_VIEW, QtHeaderFixed)
412
408
  treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
413
409
  treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
414
410
  treeHeader.setSectionsMovable(False)
@@ -448,10 +444,6 @@ class _ViewPanelKeyWords(QTreeWidget):
448
444
  def addUpdateEntry(self, tag: str, name: str, iItem: IndexItem, hItem: IndexHeading) -> None:
449
445
  """Add a new entry, or update an existing one."""
450
446
  nwItem = iItem.item
451
- docIcon = SHARED.theme.getItemIcon(
452
- nwItem.itemType, nwItem.itemClass,
453
- nwItem.itemLayout, nwItem.mainHeading
454
- )
455
447
  impLabel, impIcon = nwItem.getImportStatus()
456
448
  iLevel = nwStyles.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
457
449
  hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
@@ -468,7 +460,7 @@ class _ViewPanelKeyWords(QTreeWidget):
468
460
  trItem.setIcon(self.C_IMPORT, impIcon)
469
461
  trItem.setText(self.C_IMPORT, impLabel)
470
462
  trItem.setToolTip(self.C_IMPORT, impLabel)
471
- trItem.setIcon(self.C_DOC, docIcon)
463
+ trItem.setIcon(self.C_DOC, nwItem.getMainIcon())
472
464
  trItem.setText(self.C_DOC, nwItem.itemName)
473
465
  trItem.setToolTip(self.C_DOC, nwItem.itemName)
474
466
  trItem.setData(self.C_TITLE, QtDecoration, hDec)
@@ -25,12 +25,15 @@ from __future__ import annotations
25
25
 
26
26
  import logging
27
27
 
28
+ from enum import Enum
29
+
28
30
  from PyQt5.QtCore import pyqtSlot
29
31
  from PyQt5.QtWidgets import QGridLayout, QLabel, QWidget
30
32
 
31
33
  from novelwriter import CONFIG, SHARED
32
34
  from novelwriter.common import elide
33
35
  from novelwriter.constants import nwLabels, nwStats, trConst
36
+ from novelwriter.enum import nwChange
34
37
  from novelwriter.types import (
35
38
  QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase,
36
39
  QtAlignRightMiddle
@@ -220,19 +223,9 @@ class GuiItemDetails(QWidget):
220
223
  self.updateViewBox(self._handle)
221
224
  return
222
225
 
223
- ##
224
- # Public Slots
225
- ##
226
-
227
- @pyqtSlot(str)
228
- def updateViewBox(self, tHandle: str) -> None:
226
+ def updateViewBox(self, tHandle: str | None) -> None:
229
227
  """Populate the details box from a given handle."""
230
- if tHandle is None:
231
- self.clearDetails()
232
- return
233
-
234
- nwItem = SHARED.project.tree[tHandle]
235
- if nwItem is None:
228
+ if not (tHandle and (nwItem := SHARED.project.tree[tHandle])):
236
229
  self.clearDetails()
237
230
  return
238
231
 
@@ -269,10 +262,7 @@ class GuiItemDetails(QWidget):
269
262
  # Layout
270
263
  # ======
271
264
 
272
- usageIcon = SHARED.theme.getItemIcon(
273
- nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, nwItem.mainHeading
274
- )
275
- self.usageIcon.setPixmap(usageIcon.pixmap(iPx, iPx))
265
+ self.usageIcon.setPixmap(nwItem.getMainIcon().pixmap(iPx, iPx))
276
266
  self.usageData.setText(nwItem.describeMe())
277
267
 
278
268
  # Counts
@@ -289,13 +279,16 @@ class GuiItemDetails(QWidget):
289
279
 
290
280
  return
291
281
 
292
- @pyqtSlot(str, int, int, int)
293
- def updateCounts(self, tHandle: str, cC: int, wC: int, pC: int) -> None:
294
- """Update the counts if the handle is the same as the one we're
295
- already showing. Otherwise, do nothing.
296
- """
282
+ ##
283
+ # Public Slots
284
+ ##
285
+
286
+ @pyqtSlot(str, Enum)
287
+ def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
288
+ """Process project item change."""
297
289
  if tHandle == self._handle:
298
- self.cCountData.setText(f"{cC:n}")
299
- self.wCountData.setText(f"{wC:n}")
300
- self.pCountData.setText(f"{pC:n}")
290
+ if change == nwChange.UPDATE:
291
+ self.updateViewBox(tHandle)
292
+ elif change == nwChange.DELETE:
293
+ self.updateViewBox(None)
301
294
  return
@@ -28,7 +28,7 @@ import logging
28
28
  from pathlib import Path
29
29
  from typing import TYPE_CHECKING
30
30
 
31
- from PyQt5.QtCore import pyqtSignal, pyqtSlot
31
+ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
32
32
  from PyQt5.QtWidgets import QAction, QMenuBar
33
33
 
34
34
  from novelwriter import CONFIG, SHARED
@@ -162,19 +162,20 @@ class GuiMainMenu(QMenuBar):
162
162
  self.projMenu.addSeparator()
163
163
 
164
164
  # Project > Edit
165
- self.aEditItem = self.projMenu.addAction(self.tr("Rename Item"))
166
- self.aEditItem.setShortcut("F2")
167
- self.aEditItem.triggered.connect(qtLambda(self.mainGui.projView.renameTreeItem, None))
168
- self.mainGui.addAction(self.aEditItem)
165
+ self.aRenameItem = self.projMenu.addAction(self.tr("Rename Item"))
166
+ self.aRenameItem.setShortcut("F2")
169
167
 
170
168
  # Project > Delete
171
169
  self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
172
- self.aDeleteItem.setShortcut("Ctrl+Shift+Del") # Cannot be Ctrl+Del, see #629
173
- self.aDeleteItem.triggered.connect(qtLambda(self.mainGui.projView.requestDeleteItem, None))
170
+ self.aDeleteItem.setShortcut("Del")
171
+ self.aDeleteItem.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
174
172
 
175
173
  # Project > Empty Trash
176
174
  self.aEmptyTrash = self.projMenu.addAction(self.tr("Empty Trash"))
177
- self.aEmptyTrash.triggered.connect(qtLambda(self.mainGui.projView.emptyTrash))
175
+
176
+ self.mainGui.projView.connectMenuActions(
177
+ self.aRenameItem, self.aDeleteItem, self.aEmptyTrash
178
+ )
178
179
 
179
180
  # Project > Separator
180
181
  self.projMenu.addSeparator()
@@ -337,12 +338,16 @@ class GuiMainMenu(QMenuBar):
337
338
  # View > Go Backward
338
339
  self.aViewPrev = self.viewMenu.addAction(self.tr("Navigate Backward"))
339
340
  self.aViewPrev.setShortcut("Alt+Left")
341
+ self.aViewPrev.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
340
342
  self.aViewPrev.triggered.connect(self.mainGui.docViewer.navBackward)
343
+ self.mainGui.docViewer.addAction(self.aViewPrev)
341
344
 
342
345
  # View > Go Forward
343
346
  self.aViewNext = self.viewMenu.addAction(self.tr("Navigate Forward"))
344
347
  self.aViewNext.setShortcut("Alt+Right")
348
+ self.aViewNext.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
345
349
  self.aViewNext.triggered.connect(self.mainGui.docViewer.navForward)
350
+ self.mainGui.docViewer.addAction(self.aViewNext)
346
351
 
347
352
  # View > Separator
348
353
  self.viewMenu.addSeparator()
@@ -33,22 +33,22 @@ from time import time
33
33
  from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
34
34
  from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
35
35
  from PyQt5.QtWidgets import (
36
- QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
37
- QInputDialog, QMenu, QToolTip, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
38
- QWidget
36
+ QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QInputDialog, QMenu,
37
+ QToolTip, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
39
38
  )
40
39
 
41
40
  from novelwriter import CONFIG, SHARED
42
41
  from novelwriter.common import minmax, qtLambda
43
42
  from novelwriter.constants import nwKeyWords, nwLabels, nwStyles, trConst
44
43
  from novelwriter.core.index import IndexHeading
45
- from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
44
+ from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwOutline
46
45
  from novelwriter.extensions.modified import NIconToolButton
47
46
  from novelwriter.extensions.novelselector import NovelSelector
48
47
  from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
49
48
  from novelwriter.types import (
50
- QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtScrollAlwaysOff,
51
- QtScrollAsNeeded, QtSizeExpanding, QtUserRole
49
+ QtAlignRight, QtDecoration, QtHeaderStretch, QtHeaderToContents,
50
+ QtMouseLeft, QtMouseMiddle, QtScrollAlwaysOff, QtScrollAsNeeded,
51
+ QtSizeExpanding, QtUserRole
52
52
  )
53
53
 
54
54
  logger = logging.getLogger(__name__)
@@ -174,8 +174,8 @@ class GuiNovelView(QWidget):
174
174
  self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree"))
175
175
  return
176
176
 
177
- @pyqtSlot(str)
178
- def updateRootItem(self, tHandle: str) -> None:
177
+ @pyqtSlot(str, Enum)
178
+ def updateRootItem(self, tHandle: str, change: nwChange) -> None:
179
179
  """If any root item changes, rebuild the novel root menu."""
180
180
  self.novelBar.buildNovelRootMenu()
181
181
  return
@@ -406,10 +406,10 @@ class GuiNovelTree(QTreeWidget):
406
406
  treeHeader = self.header()
407
407
  treeHeader.setStretchLastSection(False)
408
408
  treeHeader.setMinimumSectionSize(iPx + cMg)
409
- treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.Stretch)
410
- treeHeader.setSectionResizeMode(self.C_WORDS, QHeaderView.ResizeMode.ResizeToContents)
411
- treeHeader.setSectionResizeMode(self.C_EXTRA, QHeaderView.ResizeMode.ResizeToContents)
412
- treeHeader.setSectionResizeMode(self.C_MORE, QHeaderView.ResizeMode.ResizeToContents)
409
+ treeHeader.setSectionResizeMode(self.C_TITLE, QtHeaderStretch)
410
+ treeHeader.setSectionResizeMode(self.C_WORDS, QtHeaderToContents)
411
+ treeHeader.setSectionResizeMode(self.C_EXTRA, QtHeaderToContents)
412
+ treeHeader.setSectionResizeMode(self.C_MORE, QtHeaderToContents)
413
413
 
414
414
  # Pre-Generate Tree Formatting
415
415
  fH1 = self.font()
@@ -43,7 +43,7 @@ from PyQt5.QtWidgets import (
43
43
  from novelwriter import CONFIG, SHARED
44
44
  from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
45
45
  from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst
46
- from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
46
+ from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
47
47
  from novelwriter.error import logException
48
48
  from novelwriter.extensions.configlayout import NColourLabel
49
49
  from novelwriter.extensions.novelselector import NovelSelector
@@ -165,8 +165,8 @@ class GuiOutlineView(QWidget):
165
165
  # Public Slots
166
166
  ##
167
167
 
168
- @pyqtSlot(str)
169
- def updateRootItem(self, tHandle: str) -> None:
168
+ @pyqtSlot(str, Enum)
169
+ def updateRootItem(self, tHandle: str, change: nwChange) -> None:
170
170
  """Handle tasks whenever a root folders changes."""
171
171
  self.outlineBar.populateNovelList()
172
172
  self.outlineData.updateClasses()
@@ -380,8 +380,8 @@ class GuiOutlineTree(QTreeWidget):
380
380
  self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
381
381
  self.setExpandsOnDoubleClick(False)
382
382
  self.setDragEnabled(False)
383
- self.itemDoubleClicked.connect(self._treeDoubleClick)
384
- self.itemSelectionChanged.connect(self._itemSelected)
383
+ self.itemDoubleClicked.connect(self._onItemDoubleClicked)
384
+ self.itemSelectionChanged.connect(self._onItemSelectionChanged)
385
385
 
386
386
  self.setIconSize(SHARED.theme.baseIconSize)
387
387
  self.setIndentation(0)
@@ -563,7 +563,7 @@ class GuiOutlineTree(QTreeWidget):
563
563
  ##
564
564
 
565
565
  @pyqtSlot("QTreeWidgetItem*", int)
566
- def _treeDoubleClick(self, tItem: QTreeWidgetItem, tCol: int) -> None:
566
+ def _onItemDoubleClicked(self, tItem: QTreeWidgetItem, tCol: int) -> None:
567
567
  """Extract the handle and line number of the title double-
568
568
  clicked, and send it to the main gui class for opening in the
569
569
  document editor.
@@ -574,14 +574,13 @@ class GuiOutlineTree(QTreeWidget):
574
574
  return
575
575
 
576
576
  @pyqtSlot()
577
- def _itemSelected(self) -> None:
577
+ def _onItemSelectionChanged(self) -> None:
578
578
  """Extract the handle and line number of the currently selected
579
579
  title, and send it to the details panel.
580
580
  """
581
- selItems = self.selectedItems()
582
- if selItems:
583
- tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
584
- sTitle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
581
+ if items := self.selectedItems():
582
+ tHandle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
583
+ sTitle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
585
584
  self.activeItemChanged.emit(tHandle, sTitle)
586
585
  return
587
586