novelWriter 2.4b1__py3-none-any.whl → 2.4rc1__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 (72) hide show
  1. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/METADATA +5 -6
  2. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/RECORD +62 -66
  3. novelwriter/__init__.py +5 -5
  4. novelwriter/assets/icons/none.svg +4 -0
  5. novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
  6. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  7. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +2 -2
  9. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  10. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  11. novelwriter/assets/manual.pdf +0 -0
  12. novelwriter/assets/sample.zip +0 -0
  13. novelwriter/common.py +6 -1
  14. novelwriter/config.py +8 -4
  15. novelwriter/core/coretools.py +21 -22
  16. novelwriter/core/status.py +3 -2
  17. novelwriter/core/toodt.py +332 -355
  18. novelwriter/dialogs/about.py +9 -11
  19. novelwriter/dialogs/docmerge.py +17 -14
  20. novelwriter/dialogs/docsplit.py +14 -12
  21. novelwriter/dialogs/editlabel.py +5 -4
  22. novelwriter/dialogs/preferences.py +28 -33
  23. novelwriter/dialogs/projectsettings.py +29 -26
  24. novelwriter/dialogs/quotes.py +10 -9
  25. novelwriter/dialogs/wordlist.py +15 -12
  26. novelwriter/error.py +13 -11
  27. novelwriter/extensions/circularprogress.py +12 -8
  28. novelwriter/extensions/configlayout.py +1 -3
  29. novelwriter/extensions/modified.py +33 -2
  30. novelwriter/extensions/pagedsidebar.py +16 -14
  31. novelwriter/extensions/simpleprogress.py +3 -1
  32. novelwriter/extensions/statusled.py +3 -1
  33. novelwriter/extensions/switch.py +10 -9
  34. novelwriter/extensions/switchbox.py +14 -13
  35. novelwriter/gui/doceditor.py +182 -225
  36. novelwriter/gui/dochighlight.py +4 -4
  37. novelwriter/gui/docviewer.py +53 -57
  38. novelwriter/gui/docviewerpanel.py +16 -13
  39. novelwriter/gui/editordocument.py +4 -4
  40. novelwriter/gui/itemdetails.py +45 -48
  41. novelwriter/gui/noveltree.py +22 -20
  42. novelwriter/gui/outline.py +87 -88
  43. novelwriter/gui/projtree.py +31 -29
  44. novelwriter/gui/search.py +75 -29
  45. novelwriter/gui/sidebar.py +24 -28
  46. novelwriter/gui/statusbar.py +14 -14
  47. novelwriter/gui/theme.py +47 -35
  48. novelwriter/guimain.py +35 -31
  49. novelwriter/shared.py +5 -5
  50. novelwriter/tools/dictionaries.py +13 -12
  51. novelwriter/tools/lipsum.py +20 -17
  52. novelwriter/tools/manusbuild.py +35 -27
  53. novelwriter/tools/manuscript.py +68 -73
  54. novelwriter/tools/manussettings.py +68 -73
  55. novelwriter/tools/noveldetails.py +20 -18
  56. novelwriter/tools/welcome.py +47 -43
  57. novelwriter/tools/writingstats.py +61 -55
  58. novelwriter/types.py +90 -0
  59. novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
  60. novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
  61. novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
  62. novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
  63. novelwriter/core/__init__.py +0 -3
  64. novelwriter/dialogs/__init__.py +0 -3
  65. novelwriter/extensions/__init__.py +0 -3
  66. novelwriter/gui/__init__.py +0 -3
  67. novelwriter/text/__init__.py +0 -3
  68. novelwriter/tools/__init__.py +0 -3
  69. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/LICENSE.md +0 -0
  70. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/WHEEL +0 -0
  71. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/entry_points.txt +0 -0
  72. {novelWriter-2.4b1.dist-info → novelWriter-2.4rc1.dist-info}/top_level.txt +0 -0
@@ -31,8 +31,8 @@ from enum import Enum
31
31
  from time import time
32
32
  from typing import TYPE_CHECKING
33
33
 
34
+ from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSlot, pyqtSignal
34
35
  from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
35
- from PyQt5.QtCore import QModelIndex, QPoint, Qt, QSize, pyqtSlot, pyqtSignal
36
36
  from PyQt5.QtWidgets import (
37
37
  QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
38
38
  QInputDialog, QMenu, QSizePolicy, QToolTip, QTreeWidget, QTreeWidgetItem,
@@ -47,6 +47,7 @@ from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
47
47
  from novelwriter.extensions.modified import NIconToolButton
48
48
  from novelwriter.extensions.novelselector import NovelSelector
49
49
  from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
50
+ from novelwriter.types import QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtUserRole
50
51
 
51
52
  if TYPE_CHECKING: # pragma: no cover
52
53
  from novelwriter.guimain import GuiMain
@@ -200,7 +201,7 @@ class GuiNovelToolBar(QWidget):
200
201
  self.novelView = novelView
201
202
  self.mainGui = novelView.mainGui
202
203
 
203
- iPx = SHARED.theme.baseIconSize
204
+ iSz = SHARED.theme.baseIconSize
204
205
  mPx = CONFIG.pxInt(2)
205
206
 
206
207
  self.setContentsMargins(0, 0, 0, 0)
@@ -217,12 +218,12 @@ class GuiNovelToolBar(QWidget):
217
218
  self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
218
219
  self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
219
220
 
220
- self.tbNovel = NIconToolButton(self, iPx)
221
+ self.tbNovel = NIconToolButton(self, iSz)
221
222
  self.tbNovel.setToolTip(self.tr("Novel Root"))
222
223
  self.tbNovel.clicked.connect(self.novelValue.showPopup)
223
224
 
224
225
  # Refresh Button
225
- self.tbRefresh = NIconToolButton(self, iPx)
226
+ self.tbRefresh = NIconToolButton(self, iSz)
226
227
  self.tbRefresh.setToolTip(self.tr("Refresh"))
227
228
  self.tbRefresh.clicked.connect(self._refreshNovelTree)
228
229
 
@@ -241,7 +242,7 @@ class GuiNovelToolBar(QWidget):
241
242
  self.aLastColSize = self.mLastCol.addAction(self.tr("Column Size"))
242
243
  self.aLastColSize.triggered.connect(self._selectLastColumnSize)
243
244
 
244
- self.tbMore = NIconToolButton(self, iPx)
245
+ self.tbMore = NIconToolButton(self, iSz)
245
246
  self.tbMore.setToolTip(self.tr("More Options"))
246
247
  self.tbMore.setMenu(self.mMore)
247
248
 
@@ -269,9 +270,9 @@ class GuiNovelToolBar(QWidget):
269
270
  def updateTheme(self) -> None:
270
271
  """Update theme elements."""
271
272
  # Icons
272
- self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel"))
273
- self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh"))
274
- self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
273
+ self.tbNovel.setThemeIcon("cls_novel")
274
+ self.tbRefresh.setThemeIcon("refresh")
275
+ self.tbMore.setThemeIcon("menu")
275
276
 
276
277
  qPalette = self.palette()
277
278
  qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
@@ -363,10 +364,10 @@ class GuiNovelTree(QTreeWidget):
363
364
  C_EXTRA = 2
364
365
  C_MORE = 3
365
366
 
366
- D_HANDLE = Qt.ItemDataRole.UserRole
367
- D_TITLE = Qt.ItemDataRole.UserRole + 1
368
- D_KEY = Qt.ItemDataRole.UserRole + 2
369
- D_EXTRA = Qt.ItemDataRole.UserRole + 3
367
+ D_HANDLE = QtUserRole
368
+ D_TITLE = QtUserRole + 1
369
+ D_KEY = QtUserRole + 2
370
+ D_EXTRA = QtUserRole + 3
370
371
 
371
372
  def __init__(self, novelView: GuiNovelView) -> None:
372
373
  super().__init__(parent=novelView)
@@ -391,10 +392,11 @@ class GuiNovelTree(QTreeWidget):
391
392
  # Build GUI
392
393
  # =========
393
394
 
394
- iPx = SHARED.theme.baseIconSize
395
+ iPx = SHARED.theme.baseIconHeight
396
+ iSz = SHARED.theme.baseIconSize
395
397
  cMg = CONFIG.pxInt(6)
396
398
 
397
- self.setIconSize(QSize(iPx, iPx))
399
+ self.setIconSize(iSz)
398
400
  self.setFrameStyle(QFrame.Shape.NoFrame)
399
401
  self.setUniformRowHeights(True)
400
402
  self.setAllColumnsShowFocus(True)
@@ -455,7 +457,7 @@ class GuiNovelTree(QTreeWidget):
455
457
 
456
458
  def updateTheme(self) -> None:
457
459
  """Update theme elements."""
458
- iPx = SHARED.theme.baseIconSize
460
+ iPx = SHARED.theme.baseIconHeight
459
461
  self._pMore = SHARED.theme.loadDecoration("deco_doc_more", h=iPx)
460
462
  return
461
463
 
@@ -581,12 +583,12 @@ class GuiNovelTree(QTreeWidget):
581
583
  """
582
584
  super().mousePressEvent(event)
583
585
 
584
- if event.button() == Qt.MouseButton.LeftButton:
586
+ if event.button() == QtMouseLeft:
585
587
  selItem = self.indexAt(event.pos())
586
588
  if not selItem.isValid():
587
589
  self.clearSelection()
588
590
 
589
- elif event.button() == Qt.MouseButton.MiddleButton:
591
+ elif event.button() == QtMouseMiddle:
590
592
  selItem = self.itemAt(event.pos())
591
593
  if not isinstance(selItem, QTreeWidgetItem):
592
594
  return
@@ -676,7 +678,7 @@ class GuiNovelTree(QTreeWidget):
676
678
  newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
677
679
  newItem.setData(self.C_DATA, self.D_TITLE, sTitle)
678
680
  newItem.setData(self.C_DATA, self.D_KEY, tKey)
679
- newItem.setTextAlignment(self.C_WORDS, Qt.AlignmentFlag.AlignRight)
681
+ newItem.setTextAlignment(self.C_WORDS, QtAlignRight)
680
682
 
681
683
  self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle)
682
684
  self._treeMap[tKey] = newItem
@@ -695,11 +697,11 @@ class GuiNovelTree(QTreeWidget):
695
697
  iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
696
698
  hDec = SHARED.theme.getHeaderDecoration(iLevel)
697
699
 
698
- trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
700
+ trItem.setData(self.C_TITLE, QtDecoration, hDec)
699
701
  trItem.setText(self.C_TITLE, idxItem.title)
700
702
  trItem.setFont(self.C_TITLE, self._hFonts[iLevel])
701
703
  trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}")
702
- trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore)
704
+ trItem.setData(self.C_MORE, QtDecoration, self._pMore)
703
705
 
704
706
  # Custom column
705
707
  mW = int(self._lastColSize * self.viewport().width())
@@ -33,7 +33,7 @@ import logging
33
33
  from time import time
34
34
  from enum import Enum
35
35
 
36
- from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP
36
+ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, QT_TRANSLATE_NOOP
37
37
  from PyQt5.QtWidgets import (
38
38
  QAbstractItemView, QAction, QFileDialog, QFrame, QGridLayout, QGroupBox,
39
39
  QHBoxLayout, QLabel, QMenu, QScrollArea, QSizePolicy, QSplitter, QToolBar,
@@ -48,6 +48,9 @@ from novelwriter.error import logException
48
48
  from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
49
49
  from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels
50
50
  from novelwriter.extensions.novelselector import NovelSelector
51
+ from novelwriter.types import (
52
+ QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, QtUserRole
53
+ )
51
54
 
52
55
 
53
56
  logger = logging.getLogger(__name__)
@@ -67,7 +70,7 @@ class GuiOutlineView(QWidget):
67
70
  self.outlineBar = GuiOutlineToolBar(self)
68
71
  self.outlineBar.setEnabled(False)
69
72
 
70
- self.splitOutline = QSplitter(Qt.Vertical)
73
+ self.splitOutline = QSplitter(Qt.Orientation.Vertical, self)
71
74
  self.splitOutline.addWidget(self.outlineTree)
72
75
  self.splitOutline.addWidget(self.outlineData)
73
76
  self.splitOutline.setOpaqueResize(False)
@@ -206,18 +209,18 @@ class GuiOutlineToolBar(QToolBar):
206
209
 
207
210
  logger.debug("Create: GuiOutlineToolBar")
208
211
 
209
- iPx = CONFIG.pxInt(22)
212
+ iSz = SHARED.theme.baseIconSize
210
213
  mPx = CONFIG.pxInt(12)
211
214
 
212
215
  self.setMovable(False)
213
- self.setIconSize(QSize(iPx, iPx))
216
+ self.setIconSize(iSz)
214
217
  self.setContentsMargins(0, 0, 0, 0)
215
218
 
216
219
  stretch = QWidget(self)
217
220
  stretch.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
218
221
 
219
222
  # Novel Selector
220
- self.novelLabel = QLabel(self.tr("Outline of"))
223
+ self.novelLabel = QLabel(self.tr("Outline of"), self)
221
224
  self.novelLabel.setContentsMargins(0, 0, mPx, 0)
222
225
 
223
226
  self.novelValue = NovelSelector(self)
@@ -353,8 +356,8 @@ class GuiOutlineTree(QTreeWidget):
353
356
  nwOutline.SYNOP: False,
354
357
  }
355
358
 
356
- D_HANDLE = Qt.ItemDataRole.UserRole
357
- D_TITLE = Qt.ItemDataRole.UserRole + 1
359
+ D_HANDLE = QtUserRole
360
+ D_TITLE = QtUserRole + 1
358
361
 
359
362
  hiddenStateChanged = pyqtSignal()
360
363
  activeItemChanged = pyqtSignal(str, str)
@@ -375,8 +378,7 @@ class GuiOutlineTree(QTreeWidget):
375
378
  self.itemDoubleClicked.connect(self._treeDoubleClick)
376
379
  self.itemSelectionChanged.connect(self._itemSelected)
377
380
 
378
- iPx = SHARED.theme.baseIconSize
379
- self.setIconSize(QSize(iPx, iPx))
381
+ self.setIconSize(SHARED.theme.baseIconSize)
380
382
  self.setIndentation(0)
381
383
 
382
384
  self.treeHead = self.header()
@@ -675,11 +677,11 @@ class GuiOutlineTree(QTreeWidget):
675
677
  headItem = self.headerItem()
676
678
  if isinstance(headItem, QTreeWidgetItem):
677
679
  headItem.setTextAlignment(
678
- self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
680
+ self._colIdx[nwOutline.CCOUNT], QtAlignRight)
679
681
  headItem.setTextAlignment(
680
- self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
682
+ self._colIdx[nwOutline.WCOUNT], QtAlignRight)
681
683
  headItem.setTextAlignment(
682
- self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
684
+ self._colIdx[nwOutline.PCOUNT], QtAlignRight)
683
685
 
684
686
  novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, activeOnly=True)
685
687
  for _, tHandle, sTitle, novIdx in novStruct:
@@ -692,7 +694,7 @@ class GuiOutlineTree(QTreeWidget):
692
694
  trItem = QTreeWidgetItem()
693
695
  hDec = SHARED.theme.getHeaderDecoration(iLevel)
694
696
 
695
- trItem.setData(self._colIdx[nwOutline.TITLE], Qt.ItemDataRole.DecorationRole, hDec)
697
+ trItem.setData(self._colIdx[nwOutline.TITLE], QtDecoration, hDec)
696
698
  trItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title)
697
699
  trItem.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle)
698
700
  trItem.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle)
@@ -705,9 +707,9 @@ class GuiOutlineTree(QTreeWidget):
705
707
  trItem.setText(self._colIdx[nwOutline.CCOUNT], f"{novIdx.charCount:n}")
706
708
  trItem.setText(self._colIdx[nwOutline.WCOUNT], f"{novIdx.wordCount:n}")
707
709
  trItem.setText(self._colIdx[nwOutline.PCOUNT], f"{novIdx.paraCount:n}")
708
- trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
709
- trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
710
- trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
710
+ trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], QtAlignRight)
711
+ trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], QtAlignRight)
712
+ trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], QtAlignRight)
711
713
 
712
714
  refs = SHARED.project.index.getReferences(tHandle, sTitle)
713
715
  trItem.setText(self._colIdx[nwOutline.POV], ", ".join(refs[nwKeyWords.POV_KEY]))
@@ -801,12 +803,12 @@ class GuiOutlineDetails(QScrollArea):
801
803
  bFont = SHARED.theme.guiFontB
802
804
 
803
805
  # Details Area
804
- self.titleLabel = QLabel(self.tr("Title"))
805
- self.fileLabel = QLabel(self.tr("Document"))
806
- self.itemLabel = QLabel(self.tr("Status"))
807
- self.titleValue = QLabel("")
808
- self.fileValue = QLabel("")
809
- self.itemValue = QLabel("")
806
+ self.titleLabel = QLabel(self.tr("Title"), self)
807
+ self.fileLabel = QLabel(self.tr("Document"), self)
808
+ self.itemLabel = QLabel(self.tr("Status"), self)
809
+ self.titleValue = QLabel("", self)
810
+ self.fileValue = QLabel("", self)
811
+ self.itemValue = QLabel("", self)
810
812
 
811
813
  self.titleLabel.setFont(bFont)
812
814
  self.fileLabel.setFont(bFont)
@@ -820,12 +822,12 @@ class GuiOutlineDetails(QScrollArea):
820
822
  self.itemValue.setMaximumWidth(maxTitle)
821
823
 
822
824
  # Stats Area
823
- self.cCLabel = QLabel(self.tr("Characters"))
824
- self.wCLabel = QLabel(self.tr("Words"))
825
- self.pCLabel = QLabel(self.tr("Paragraphs"))
826
- self.cCValue = QLabel("")
827
- self.wCValue = QLabel("")
828
- self.pCValue = QLabel("")
825
+ self.cCLabel = QLabel(self.tr("Characters"), self)
826
+ self.wCLabel = QLabel(self.tr("Words"), self)
827
+ self.pCLabel = QLabel(self.tr("Paragraphs"), self)
828
+ self.cCValue = QLabel("", self)
829
+ self.wCValue = QLabel("", self)
830
+ self.pCValue = QLabel("", self)
829
831
 
830
832
  self.cCLabel.setFont(bFont)
831
833
  self.wCLabel.setFont(bFont)
@@ -834,31 +836,31 @@ class GuiOutlineDetails(QScrollArea):
834
836
  self.cCValue.setMinimumWidth(wCount)
835
837
  self.wCValue.setMinimumWidth(wCount)
836
838
  self.pCValue.setMinimumWidth(wCount)
837
- self.cCValue.setAlignment(Qt.AlignRight)
838
- self.wCValue.setAlignment(Qt.AlignRight)
839
- self.pCValue.setAlignment(Qt.AlignRight)
839
+ self.cCValue.setAlignment(QtAlignRight)
840
+ self.wCValue.setAlignment(QtAlignRight)
841
+ self.pCValue.setAlignment(QtAlignRight)
840
842
 
841
843
  # Synopsis
842
- self.synopLabel = QLabel(self.tr("Synopsis"))
844
+ self.synopLabel = QLabel(self.tr("Synopsis"), self)
843
845
  self.synopLabel.setFont(bFont)
844
846
 
845
- self.synopValue = QLabel("")
847
+ self.synopValue = QLabel("", self)
846
848
  self.synopValue.setWordWrap(True)
847
- self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
849
+ self.synopValue.setAlignment(QtAlignLeftTop)
848
850
 
849
851
  self.synopLWrap = QHBoxLayout()
850
852
  self.synopLWrap.addWidget(self.synopValue, 1)
851
853
 
852
854
  # Tags
853
- self.povKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
854
- self.focKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
855
- self.chrKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
856
- self.pltKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
857
- self.timKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
858
- self.wldKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
859
- self.objKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
860
- self.entKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
861
- self.cstKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
855
+ self.povKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]), self)
856
+ self.focKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]), self)
857
+ self.chrKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]), self)
858
+ self.pltKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]), self)
859
+ self.timKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]), self)
860
+ self.wldKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]), self)
861
+ self.objKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]), self)
862
+ self.entKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]), self)
863
+ self.cstKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]), self)
862
864
 
863
865
  self.povKeyLabel.setFont(bFont)
864
866
  self.focKeyLabel.setFont(bFont)
@@ -880,15 +882,15 @@ class GuiOutlineDetails(QScrollArea):
880
882
  self.entKeyLWrap = QHBoxLayout()
881
883
  self.cstKeyLWrap = QHBoxLayout()
882
884
 
883
- self.povKeyValue = QLabel("")
884
- self.focKeyValue = QLabel("")
885
- self.chrKeyValue = QLabel("")
886
- self.pltKeyValue = QLabel("")
887
- self.timKeyValue = QLabel("")
888
- self.wldKeyValue = QLabel("")
889
- self.objKeyValue = QLabel("")
890
- self.entKeyValue = QLabel("")
891
- self.cstKeyValue = QLabel("")
885
+ self.povKeyValue = QLabel("", self)
886
+ self.focKeyValue = QLabel("", self)
887
+ self.chrKeyValue = QLabel("", self)
888
+ self.pltKeyValue = QLabel("", self)
889
+ self.timKeyValue = QLabel("", self)
890
+ self.wldKeyValue = QLabel("", self)
891
+ self.objKeyValue = QLabel("", self)
892
+ self.entKeyValue = QLabel("", self)
893
+ self.cstKeyValue = QLabel("", self)
892
894
 
893
895
  self.povKeyValue.setWordWrap(True)
894
896
  self.focKeyValue.setWordWrap(True)
@@ -925,23 +927,20 @@ class GuiOutlineDetails(QScrollArea):
925
927
  self.mainForm = QGridLayout()
926
928
  self.mainGroup.setLayout(self.mainForm)
927
929
 
928
- topLeft = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft
929
- topRight = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight
930
-
931
- self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, topLeft)
932
- self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, topLeft)
933
- self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, topLeft)
934
- self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, topRight)
935
- self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, topLeft)
936
- self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, topLeft)
937
- self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, topLeft)
938
- self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, topRight)
939
- self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, topLeft)
940
- self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, topLeft)
941
- self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, topLeft)
942
- self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, topRight)
943
- self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, topLeft)
944
- self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, topLeft)
930
+ self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, QtAlignLeftTop)
931
+ self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, QtAlignLeftTop)
932
+ self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, QtAlignLeftTop)
933
+ self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, QtAlignRightTop)
934
+ self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, QtAlignLeftTop)
935
+ self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, QtAlignLeftTop)
936
+ self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, QtAlignLeftTop)
937
+ self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, QtAlignRightTop)
938
+ self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, QtAlignLeftTop)
939
+ self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, QtAlignLeftTop)
940
+ self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, QtAlignLeftTop)
941
+ self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, QtAlignRightTop)
942
+ self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, QtAlignLeftTop)
943
+ self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, QtAlignLeftTop)
945
944
 
946
945
  self.mainForm.setColumnStretch(1, 1)
947
946
  self.mainForm.setRowStretch(4, 1)
@@ -953,24 +952,24 @@ class GuiOutlineDetails(QScrollArea):
953
952
  self.tagsForm = QGridLayout()
954
953
  self.tagsGroup.setLayout(self.tagsForm)
955
954
 
956
- self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, topLeft)
957
- self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, topLeft)
958
- self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, topLeft)
959
- self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, topLeft)
960
- self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, topLeft)
961
- self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, topLeft)
962
- self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, topLeft)
963
- self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, topLeft)
964
- self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, topLeft)
965
- self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, topLeft)
966
- self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, topLeft)
967
- self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, topLeft)
968
- self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, topLeft)
969
- self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, topLeft)
970
- self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, topLeft)
971
- self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, topLeft)
972
- self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, topLeft)
973
- self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, topLeft)
955
+ self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, QtAlignLeftTop)
956
+ self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, QtAlignLeftTop)
957
+ self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, QtAlignLeftTop)
958
+ self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, QtAlignLeftTop)
959
+ self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, QtAlignLeftTop)
960
+ self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, QtAlignLeftTop)
961
+ self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, QtAlignLeftTop)
962
+ self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, QtAlignLeftTop)
963
+ self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, QtAlignLeftTop)
964
+ self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, QtAlignLeftTop)
965
+ self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, QtAlignLeftTop)
966
+ self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, QtAlignLeftTop)
967
+ self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, QtAlignLeftTop)
968
+ self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, QtAlignLeftTop)
969
+ self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, QtAlignLeftTop)
970
+ self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, QtAlignLeftTop)
971
+ self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, QtAlignLeftTop)
972
+ self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, QtAlignLeftTop)
974
973
 
975
974
  self.tagsForm.setColumnStretch(1, 1)
976
975
  self.tagsForm.setRowStretch(8, 1)
@@ -978,7 +977,7 @@ class GuiOutlineDetails(QScrollArea):
978
977
  self.tagsForm.setVerticalSpacing(vSpace)
979
978
 
980
979
  # Assemble
981
- self.outerWidget = QWidget()
980
+ self.outerWidget = QWidget(self)
982
981
  self.outerBox = QHBoxLayout()
983
982
  self.outerBox.addWidget(self.mainGroup, 0)
984
983
  self.outerBox.addWidget(self.tagsGroup, 1)
@@ -32,10 +32,10 @@ from enum import Enum
32
32
  from time import time
33
33
  from typing import TYPE_CHECKING
34
34
 
35
+ from PyQt5.QtCore import QPoint, QTimer, Qt, pyqtSignal, pyqtSlot
35
36
  from PyQt5.QtGui import (
36
37
  QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
37
38
  )
38
- from PyQt5.QtCore import QPoint, QTimer, Qt, QSize, pyqtSignal, pyqtSlot
39
39
  from PyQt5.QtWidgets import (
40
40
  QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView,
41
41
  QLabel, QMenu, QShortcut, QSizePolicy, QTreeWidget, QTreeWidgetItem,
@@ -54,6 +54,7 @@ from novelwriter.dialogs.projectsettings import GuiProjectSettings
54
54
  from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout
55
55
  from novelwriter.extensions.modified import NIconToolButton
56
56
  from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
57
+ from novelwriter.types import QtAlignLeft, QtAlignRight, QtMouseLeft, QtMouseMiddle, QtUserRole
57
58
 
58
59
  if TYPE_CHECKING: # pragma: no cover
59
60
  from novelwriter.guimain import GuiMain
@@ -263,14 +264,14 @@ class GuiProjectToolBar(QWidget):
263
264
  self.projTree = projView.projTree
264
265
  self.mainGui = projView.mainGui
265
266
 
266
- iPx = SHARED.theme.baseIconSize
267
+ iSz = SHARED.theme.baseIconSize
267
268
  mPx = CONFIG.pxInt(2)
268
269
 
269
270
  self.setContentsMargins(0, 0, 0, 0)
270
271
  self.setAutoFillBackground(True)
271
272
 
272
273
  # Widget Label
273
- self.viewLabel = QLabel(self.tr("Project Content"))
274
+ self.viewLabel = QLabel(self.tr("Project Content"), self)
274
275
  self.viewLabel.setFont(SHARED.theme.guiFontB)
275
276
  self.viewLabel.setContentsMargins(0, 0, 0, 0)
276
277
  self.viewLabel.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
@@ -278,17 +279,17 @@ class GuiProjectToolBar(QWidget):
278
279
  # Quick Links
279
280
  self.mQuick = QMenu(self)
280
281
 
281
- self.tbQuick = NIconToolButton(self, iPx)
282
+ self.tbQuick = NIconToolButton(self, iSz)
282
283
  self.tbQuick.setToolTip("%s [Ctrl+L]" % self.tr("Quick Links"))
283
284
  self.tbQuick.setShortcut("Ctrl+L")
284
285
  self.tbQuick.setMenu(self.mQuick)
285
286
 
286
287
  # Move Buttons
287
- self.tbMoveU = NIconToolButton(self, iPx)
288
+ self.tbMoveU = NIconToolButton(self, iSz)
288
289
  self.tbMoveU.setToolTip("%s [Ctrl+Up]" % self.tr("Move Up"))
289
290
  self.tbMoveU.clicked.connect(lambda: self.projTree.moveTreeItem(-1))
290
291
 
291
- self.tbMoveD = NIconToolButton(self, iPx)
292
+ self.tbMoveD = NIconToolButton(self, iSz)
292
293
  self.tbMoveD.setToolTip("%s [Ctrl+Down]" % self.tr("Move Down"))
293
294
  self.tbMoveD.clicked.connect(lambda: self.projTree.moveTreeItem(1))
294
295
 
@@ -328,7 +329,7 @@ class GuiProjectToolBar(QWidget):
328
329
  self.mAddRoot = self.mAdd.addMenu(trConst(nwLabels.ITEM_DESCRIPTION["root"]))
329
330
  self._buildRootMenu()
330
331
 
331
- self.tbAdd = NIconToolButton(self, iPx)
332
+ self.tbAdd = NIconToolButton(self, iSz)
332
333
  self.tbAdd.setToolTip("%s [Ctrl+N]" % self.tr("Add Item"))
333
334
  self.tbAdd.setShortcut("Ctrl+N")
334
335
  self.tbAdd.setMenu(self.mAdd)
@@ -345,7 +346,7 @@ class GuiProjectToolBar(QWidget):
345
346
  self.aEmptyTrash = self.mMore.addAction(self.tr("Empty Trash"))
346
347
  self.aEmptyTrash.triggered.connect(lambda: self.projTree.emptyTrash())
347
348
 
348
- self.tbMore = NIconToolButton(self, iPx)
349
+ self.tbMore = NIconToolButton(self, iSz)
349
350
  self.tbMore.setToolTip(self.tr("More Options"))
350
351
  self.tbMore.setMenu(self.mMore)
351
352
 
@@ -384,16 +385,17 @@ class GuiProjectToolBar(QWidget):
384
385
  self.tbAdd.setStyleSheet(buttonStyle)
385
386
  self.tbMore.setStyleSheet(buttonStyle)
386
387
 
387
- self.tbQuick.setIcon(SHARED.theme.getIcon("bookmark"))
388
- self.tbMoveU.setIcon(SHARED.theme.getIcon("up"))
389
- self.tbMoveD.setIcon(SHARED.theme.getIcon("down"))
388
+ self.tbQuick.setThemeIcon("bookmark")
389
+ self.tbMoveU.setThemeIcon("up")
390
+ self.tbMoveD.setThemeIcon("down")
391
+ self.tbAdd.setThemeIcon("add")
392
+ self.tbMore.setThemeIcon("menu")
393
+
390
394
  self.aAddEmpty.setIcon(SHARED.theme.getIcon("proj_document"))
391
395
  self.aAddChap.setIcon(SHARED.theme.getIcon("proj_chapter"))
392
396
  self.aAddScene.setIcon(SHARED.theme.getIcon("proj_scene"))
393
397
  self.aAddNote.setIcon(SHARED.theme.getIcon("proj_note"))
394
398
  self.aAddFolder.setIcon(SHARED.theme.getIcon("proj_folder"))
395
- self.tbAdd.setIcon(SHARED.theme.getIcon("add"))
396
- self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
397
399
 
398
400
  self.buildQuickLinksMenu()
399
401
  self._buildRootMenu()
@@ -485,8 +487,8 @@ class GuiProjectTree(QTreeWidget):
485
487
  C_ACTIVE = 2
486
488
  C_STATUS = 3
487
489
 
488
- D_HANDLE = Qt.ItemDataRole.UserRole
489
- D_WORDS = Qt.ItemDataRole.UserRole + 1
490
+ D_HANDLE = QtUserRole
491
+ D_WORDS = QtUserRole + 1
490
492
 
491
493
  itemRefreshed = pyqtSignal(str, NWItem, QIcon)
492
494
 
@@ -516,10 +518,10 @@ class GuiProjectTree(QTreeWidget):
516
518
  self.customContextMenuRequested.connect(self._openContextMenu)
517
519
 
518
520
  # Tree Settings
519
- iPx = SHARED.theme.baseIconSize
521
+ iPx = SHARED.theme.baseIconHeight
520
522
  cMg = CONFIG.pxInt(6)
521
523
 
522
- self.setIconSize(QSize(iPx, iPx))
524
+ self.setIconSize(SHARED.theme.baseIconSize)
523
525
  self.setFrameStyle(QFrame.Shape.NoFrame)
524
526
  self.setUniformRowHeights(True)
525
527
  self.setAllColumnsShowFocus(True)
@@ -563,9 +565,9 @@ class GuiProjectTree(QTreeWidget):
563
565
  self.itemSelectionChanged.connect(self._treeSelectionChange)
564
566
 
565
567
  # Auto Scroll
566
- self._scrollMargin = SHARED.theme.baseIconSize
568
+ self._scrollMargin = SHARED.theme.baseIconHeight
567
569
  self._scrollDirection = 0
568
- self._scrollTimer = QTimer()
570
+ self._scrollTimer = QTimer(self)
569
571
  self._scrollTimer.timeout.connect(self._doAutoScroll)
570
572
  self._scrollTimer.setInterval(250)
571
573
 
@@ -1228,7 +1230,7 @@ class GuiProjectTree(QTreeWidget):
1228
1230
  else:
1229
1231
  ctxMenu.buildSingleSelectMenu(hasChild)
1230
1232
 
1231
- ctxMenu.exec_(self.viewport().mapToGlobal(clickPos))
1233
+ ctxMenu.exec(self.viewport().mapToGlobal(clickPos))
1232
1234
  ctxMenu.deleteLater()
1233
1235
 
1234
1236
  return True
@@ -1254,11 +1256,11 @@ class GuiProjectTree(QTreeWidget):
1254
1256
  for viewing if the user middle-clicked.
1255
1257
  """
1256
1258
  super().mousePressEvent(event)
1257
- if event.button() == Qt.MouseButton.LeftButton:
1259
+ if event.button() == QtMouseLeft:
1258
1260
  selItem = self.indexAt(event.pos())
1259
1261
  if not selItem.isValid():
1260
1262
  self.clearSelection()
1261
- elif event.button() == Qt.MouseButton.MiddleButton:
1263
+ elif event.button() == QtMouseMiddle:
1262
1264
  selItem = self.itemAt(event.pos())
1263
1265
  if selItem:
1264
1266
  tHandle = selItem.data(self.C_DATA, self.D_HANDLE)
@@ -1266,7 +1268,7 @@ class GuiProjectTree(QTreeWidget):
1266
1268
  self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", False)
1267
1269
  return
1268
1270
 
1269
- def startDrag(self, dropAction: Qt.DropActions) -> None:
1271
+ def startDrag(self, dropAction: Qt.DropAction) -> None:
1270
1272
  """Capture the drag and drop handling to pop alerts."""
1271
1273
  super().startDrag(dropAction)
1272
1274
  if self._popAlert:
@@ -1408,7 +1410,7 @@ class GuiProjectTree(QTreeWidget):
1408
1410
  itemList.remove(tHandle)
1409
1411
 
1410
1412
  dlgMerge = GuiDocMerge(self.mainGui, tHandle, itemList)
1411
- dlgMerge.exec_()
1413
+ dlgMerge.exec()
1412
1414
 
1413
1415
  if dlgMerge.result() == QDialog.DialogCode.Accepted:
1414
1416
 
@@ -1478,7 +1480,7 @@ class GuiProjectTree(QTreeWidget):
1478
1480
  return False
1479
1481
 
1480
1482
  dlgSplit = GuiDocSplit(self.mainGui, tHandle)
1481
- dlgSplit.exec_()
1483
+ dlgSplit.exec()
1482
1484
 
1483
1485
  if dlgSplit.result() == QDialog.DialogCode.Accepted:
1484
1486
 
@@ -1585,10 +1587,10 @@ class GuiProjectTree(QTreeWidget):
1585
1587
  newItem.setText(self.C_ACTIVE, "")
1586
1588
  newItem.setText(self.C_STATUS, "")
1587
1589
 
1588
- newItem.setTextAlignment(self.C_NAME, Qt.AlignmentFlag.AlignLeft)
1589
- newItem.setTextAlignment(self.C_COUNT, Qt.AlignmentFlag.AlignRight)
1590
- newItem.setTextAlignment(self.C_ACTIVE, Qt.AlignmentFlag.AlignLeft)
1591
- newItem.setTextAlignment(self.C_STATUS, Qt.AlignmentFlag.AlignLeft)
1590
+ newItem.setTextAlignment(self.C_NAME, QtAlignLeft)
1591
+ newItem.setTextAlignment(self.C_COUNT, QtAlignRight)
1592
+ newItem.setTextAlignment(self.C_ACTIVE, QtAlignLeft)
1593
+ newItem.setTextAlignment(self.C_STATUS, QtAlignLeft)
1592
1594
 
1593
1595
  newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
1594
1596
  newItem.setData(self.C_DATA, self.D_WORDS, 0)