novelWriter 2.6b1__py3-none-any.whl → 2.6rc1__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 (114) hide show
  1. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/METADATA +4 -4
  2. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/RECORD +114 -98
  3. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +50 -11
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  9. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  10. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  11. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  12. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  13. novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
  14. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  15. novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
  16. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  17. novelwriter/assets/i18n/project_de_DE.json +2 -2
  18. novelwriter/assets/i18n/project_ru_RU.json +11 -0
  19. novelwriter/assets/icons/typicons_dark/icons.conf +7 -0
  20. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
  21. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
  22. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
  23. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
  24. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
  25. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
  26. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
  27. novelwriter/assets/icons/typicons_light/icons.conf +7 -0
  28. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
  29. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
  30. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
  31. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
  32. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
  33. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
  34. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
  35. novelwriter/assets/manual.pdf +0 -0
  36. novelwriter/assets/sample.zip +0 -0
  37. novelwriter/assets/text/credits_en.htm +1 -0
  38. novelwriter/common.py +38 -3
  39. novelwriter/config.py +19 -13
  40. novelwriter/constants.py +60 -45
  41. novelwriter/core/buildsettings.py +1 -1
  42. novelwriter/core/coretools.py +112 -126
  43. novelwriter/core/docbuild.py +4 -3
  44. novelwriter/core/document.py +1 -1
  45. novelwriter/core/index.py +10 -20
  46. novelwriter/core/item.py +40 -7
  47. novelwriter/core/itemmodel.py +518 -0
  48. novelwriter/core/options.py +1 -1
  49. novelwriter/core/project.py +68 -90
  50. novelwriter/core/projectdata.py +8 -2
  51. novelwriter/core/projectxml.py +1 -1
  52. novelwriter/core/sessions.py +1 -1
  53. novelwriter/core/spellcheck.py +1 -1
  54. novelwriter/core/status.py +24 -8
  55. novelwriter/core/storage.py +1 -1
  56. novelwriter/core/tree.py +269 -288
  57. novelwriter/dialogs/about.py +1 -1
  58. novelwriter/dialogs/docmerge.py +8 -18
  59. novelwriter/dialogs/docsplit.py +1 -1
  60. novelwriter/dialogs/editlabel.py +1 -1
  61. novelwriter/dialogs/preferences.py +4 -4
  62. novelwriter/dialogs/projectsettings.py +148 -98
  63. novelwriter/dialogs/quotes.py +1 -1
  64. novelwriter/dialogs/wordlist.py +11 -10
  65. novelwriter/enum.py +8 -1
  66. novelwriter/error.py +2 -2
  67. novelwriter/extensions/configlayout.py +7 -5
  68. novelwriter/extensions/eventfilters.py +1 -1
  69. novelwriter/extensions/modified.py +17 -5
  70. novelwriter/extensions/novelselector.py +1 -1
  71. novelwriter/extensions/pagedsidebar.py +4 -4
  72. novelwriter/extensions/progressbars.py +4 -4
  73. novelwriter/extensions/statusled.py +3 -3
  74. novelwriter/extensions/switch.py +3 -3
  75. novelwriter/extensions/switchbox.py +1 -1
  76. novelwriter/extensions/versioninfo.py +1 -1
  77. novelwriter/formats/shared.py +1 -1
  78. novelwriter/formats/todocx.py +35 -39
  79. novelwriter/formats/tohtml.py +15 -16
  80. novelwriter/formats/tokenizer.py +26 -22
  81. novelwriter/formats/tomarkdown.py +1 -1
  82. novelwriter/formats/toodt.py +54 -125
  83. novelwriter/formats/toqdoc.py +93 -45
  84. novelwriter/formats/toraw.py +1 -1
  85. novelwriter/gui/doceditor.py +233 -220
  86. novelwriter/gui/dochighlight.py +1 -1
  87. novelwriter/gui/docviewer.py +39 -10
  88. novelwriter/gui/docviewerpanel.py +15 -23
  89. novelwriter/gui/editordocument.py +1 -1
  90. novelwriter/gui/itemdetails.py +20 -27
  91. novelwriter/gui/mainmenu.py +14 -9
  92. novelwriter/gui/noveltree.py +13 -13
  93. novelwriter/gui/outline.py +18 -20
  94. novelwriter/gui/projtree.py +545 -1201
  95. novelwriter/gui/search.py +11 -19
  96. novelwriter/gui/sidebar.py +1 -1
  97. novelwriter/gui/statusbar.py +20 -3
  98. novelwriter/gui/theme.py +8 -4
  99. novelwriter/guimain.py +60 -48
  100. novelwriter/shared.py +53 -24
  101. novelwriter/text/counting.py +1 -1
  102. novelwriter/text/patterns.py +18 -6
  103. novelwriter/tools/dictionaries.py +1 -1
  104. novelwriter/tools/lipsum.py +1 -1
  105. novelwriter/tools/manusbuild.py +14 -12
  106. novelwriter/tools/manuscript.py +7 -7
  107. novelwriter/tools/manussettings.py +43 -53
  108. novelwriter/tools/noveldetails.py +1 -1
  109. novelwriter/tools/welcome.py +1 -1
  110. novelwriter/tools/writingstats.py +1 -1
  111. novelwriter/types.py +9 -3
  112. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/LICENSE.md +0 -0
  113. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/entry_points.txt +0 -0
  114. {novelWriter-2.6b1.dist-info → novelWriter-2.6rc1.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2023-05-24 [2.1b1] GuiManuscriptBuild
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -179,14 +179,20 @@ class GuiManuscriptBuild(NDialog):
179
179
  self.buildBox.setVerticalSpacing(sp4)
180
180
 
181
181
  # Dialog Buttons
182
+ self.buttonBox = QDialogButtonBox(self)
183
+
182
184
  self.btnOpen = QPushButton(SHARED.theme.getIcon("browse"), self.tr("Open Folder"), self)
183
185
  self.btnOpen.setIconSize(bSz)
186
+ self.btnOpen.setAutoDefault(False)
187
+ self.buttonBox.addButton(self.btnOpen, QtRoleAction)
188
+
184
189
  self.btnBuild = QPushButton(SHARED.theme.getIcon("export"), self.tr("&Build"), self)
185
190
  self.btnBuild.setIconSize(bSz)
191
+ self.btnBuild.setAutoDefault(True)
192
+ self.buttonBox.addButton(self.btnBuild, QtRoleAction)
186
193
 
187
- self.dlgButtons = QDialogButtonBox(QtDialogClose, self)
188
- self.dlgButtons.addButton(self.btnOpen, QtRoleAction)
189
- self.dlgButtons.addButton(self.btnBuild, QtRoleAction)
194
+ self.btnClose = self.buttonBox.addButton(QtDialogClose)
195
+ self.btnClose.setAutoDefault(False)
190
196
 
191
197
  # Assemble GUI
192
198
  # ============
@@ -213,7 +219,7 @@ class GuiManuscriptBuild(NDialog):
213
219
  self.outerBox.addSpacing(sp4)
214
220
  self.outerBox.addLayout(self.buildBox, 0)
215
221
  self.outerBox.addSpacing(sp16)
216
- self.outerBox.addWidget(self.dlgButtons, 0)
222
+ self.outerBox.addWidget(self.buttonBox, 0)
217
223
  self.outerBox.setSpacing(0)
218
224
 
219
225
  self.setLayout(self.outerBox)
@@ -229,7 +235,7 @@ class GuiManuscriptBuild(NDialog):
229
235
  # Signals
230
236
  self.btnReset.clicked.connect(self._doResetBuildName)
231
237
  self.btnBrowse.clicked.connect(self._doSelectPath)
232
- self.dlgButtons.clicked.connect(self._dialogButtonClicked)
238
+ self.buttonBox.clicked.connect(self._dialogButtonClicked)
233
239
  self.listFormats.itemSelectionChanged.connect(self._resetProgress)
234
240
 
235
241
  logger.debug("Ready: GuiManuscriptBuild")
@@ -260,7 +266,7 @@ class GuiManuscriptBuild(NDialog):
260
266
  @pyqtSlot("QAbstractButton*")
261
267
  def _dialogButtonClicked(self, button: QAbstractButton) -> None:
262
268
  """Handle button clicks from the dialog button box."""
263
- role = self.dlgButtons.buttonRole(button)
269
+ role = self.buttonBox.buttonRole(button)
264
270
  if role == QtRoleAction:
265
271
  if button == self.btnBuild:
266
272
  self._runBuild()
@@ -388,13 +394,9 @@ class GuiManuscriptBuild(NDialog):
388
394
  if isinstance(rItem, NWItem):
389
395
  rootMap[rHandle] = rItem.itemName
390
396
 
391
- itemIcon = SHARED.theme.getItemIcon(
392
- nwItem.itemType, nwItem.itemClass,
393
- nwItem.itemLayout, nwItem.mainHeading
394
- )
395
397
  rootName = rootMap.get(rHandle, "??????")
396
398
  item = QListWidgetItem(f"{rootName}: {nwItem.itemName}")
397
- item.setIcon(itemIcon)
399
+ item.setIcon(nwItem.getMainIcon())
398
400
  self.listContent.addItem(item)
399
401
 
400
402
  return
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2023-05-13 [2.1b1] GuiManuscript
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -986,17 +986,17 @@ class _StatsWidget(QWidget):
986
986
  def updateStats(self, data: dict[str, int]) -> None:
987
987
  """Update the stats values from a Tokenizer stats dict."""
988
988
  # Minimal
989
- self.minWordCount.setText("{0:n}".format(data.get(nwStats.WORDS_ALL, 0)))
990
- self.minCharCount.setText("{0:n}".format(data.get(nwStats.CHARS_ALL, 0)))
989
+ self.minWordCount.setText("{0:n}".format(data.get(nwStats.WORDS, 0)))
990
+ self.minCharCount.setText("{0:n}".format(data.get(nwStats.CHARS, 0)))
991
991
 
992
992
  # Maximal
993
- self.maxTotalWords.setText("{0:n}".format(data.get(nwStats.WORDS_ALL, 0)))
993
+ self.maxTotalWords.setText("{0:n}".format(data.get(nwStats.WORDS, 0)))
994
994
  self.maxHeadWords.setText("{0:n}".format(data.get(nwStats.WORDS_TITLE, 0)))
995
995
  self.maxTextWords.setText("{0:n}".format(data.get(nwStats.WORDS_TEXT, 0)))
996
996
  self.maxTitleCount.setText("{0:n}".format(data.get(nwStats.TITLES, 0)))
997
997
  self.maxParCount.setText("{0:n}".format(data.get(nwStats.PARAGRAPHS, 0)))
998
998
 
999
- self.maxTotalChars.setText("{0:n}".format(data.get(nwStats.CHARS_ALL, 0)))
999
+ self.maxTotalChars.setText("{0:n}".format(data.get(nwStats.CHARS, 0)))
1000
1000
  self.maxHeaderChars.setText("{0:n}".format(data.get(nwStats.CHARS_TITLE, 0)))
1001
1001
  self.maxTextChars.setText("{0:n}".format(data.get(nwStats.CHARS_TEXT, 0)))
1002
1002
 
@@ -1037,7 +1037,7 @@ class _StatsWidget(QWidget):
1037
1037
  hPx = CONFIG.pxInt(12)
1038
1038
  vPx = CONFIG.pxInt(4)
1039
1039
 
1040
- trAllChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_ALL])
1040
+ trAllChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS])
1041
1041
  trTextChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_TEXT])
1042
1042
  trTitleChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_TITLE])
1043
1043
  trParagraphCount = trConst(nwLabels.STATS_NAME[nwStats.PARAGRAPHS])
@@ -1045,7 +1045,7 @@ class _StatsWidget(QWidget):
1045
1045
  trAllWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_ALL])
1046
1046
  trTextWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_TEXT])
1047
1047
  trTitleWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_TITLE])
1048
- trAllWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_ALL])
1048
+ trAllWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS])
1049
1049
  trTextWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_TEXT])
1050
1050
  trTitleWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_TITLE])
1051
1051
 
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2023-02-13 [2.1b1] GuiBuildSettings
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -31,13 +31,13 @@ from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
31
31
  from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
32
32
  from PyQt5.QtWidgets import (
33
33
  QAbstractButton, QAbstractItemView, QDialogButtonBox, QFrame, QGridLayout,
34
- QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QPlainTextEdit,
35
- QPushButton, QSplitter, QStackedWidget, QTreeWidget, QTreeWidgetItem,
36
- QVBoxLayout, QWidget
34
+ QHBoxLayout, QLabel, QLineEdit, QMenu, QPlainTextEdit, QPushButton,
35
+ QSplitter, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
36
+ QWidget
37
37
  )
38
38
 
39
39
  from novelwriter import CONFIG, SHARED
40
- from novelwriter.common import describeFont, qtLambda
40
+ from novelwriter.common import describeFont, fontMatcher, qtLambda
41
41
  from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles, trConst
42
42
  from novelwriter.core.buildsettings import BuildSettings, FilterMode
43
43
  from novelwriter.extensions.configlayout import (
@@ -51,7 +51,8 @@ from novelwriter.extensions.switch import NSwitch
51
51
  from novelwriter.extensions.switchbox import NSwitchBox
52
52
  from novelwriter.types import (
53
53
  QtAlignCenter, QtAlignLeft, QtDialogApply, QtDialogClose, QtDialogSave,
54
- QtRoleAccept, QtRoleApply, QtRoleReject, QtUserRole
54
+ QtHeaderFixed, QtHeaderStretch, QtRoleAccept, QtRoleApply, QtRoleReject,
55
+ QtUserRole
55
56
  )
56
57
 
57
58
  if TYPE_CHECKING: # pragma: no cover
@@ -313,9 +314,9 @@ class _FilterTab(NFixedPage):
313
314
  treeHeader = self.optTree.header()
314
315
  treeHeader.setStretchLastSection(False)
315
316
  treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1551
316
- treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.Stretch)
317
- treeHeader.setSectionResizeMode(self.C_ACTIVE, QHeaderView.ResizeMode.Fixed)
318
- treeHeader.setSectionResizeMode(self.C_STATUS, QHeaderView.ResizeMode.Fixed)
317
+ treeHeader.setSectionResizeMode(self.C_NAME, QtHeaderStretch)
318
+ treeHeader.setSectionResizeMode(self.C_ACTIVE, QtHeaderFixed)
319
+ treeHeader.setSectionResizeMode(self.C_STATUS, QtHeaderFixed)
319
320
  treeHeader.resizeSection(self.C_ACTIVE, iPx + cMg)
320
321
  treeHeader.resizeSection(self.C_STATUS, iPx + cMg)
321
322
 
@@ -418,8 +419,7 @@ class _FilterTab(NFixedPage):
418
419
  logger.debug("Building project tree")
419
420
  self._treeMap = {}
420
421
  self.optTree.clear()
421
- for nwItem in SHARED.project.iterProjectItems():
422
-
422
+ for nwItem in SHARED.project.tree:
423
423
  tHandle = nwItem.itemHandle
424
424
  pHandle = nwItem.itemParent
425
425
  rHandle = nwItem.itemRoot
@@ -428,28 +428,15 @@ class _FilterTab(NFixedPage):
428
428
  continue
429
429
 
430
430
  isFile = nwItem.isFileType()
431
- isActive = nwItem.isActive
432
-
433
431
  if nwItem.isInactiveClass() or not self._build.isRootAllowed(rHandle):
434
432
  continue
435
433
 
436
- hLevel = nwItem.mainHeading
437
- itemIcon = SHARED.theme.getItemIcon(
438
- nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
439
- )
440
-
441
- if isFile:
442
- iconName = "checked" if isActive else "unchecked"
443
- else:
444
- iconName = "noncheckable"
445
-
446
434
  trItem = QTreeWidgetItem()
447
- trItem.setIcon(self.C_NAME, itemIcon)
435
+ trItem.setIcon(self.C_NAME, nwItem.getMainIcon())
448
436
  trItem.setText(self.C_NAME, nwItem.itemName)
449
437
  trItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
450
438
  trItem.setData(self.C_DATA, self.D_FILE, isFile)
451
- trItem.setIcon(self.C_ACTIVE, SHARED.theme.getIcon(iconName))
452
-
439
+ trItem.setIcon(self.C_ACTIVE, nwItem.getActiveStatus()[1])
453
440
  trItem.setTextAlignment(self.C_NAME, QtAlignLeft)
454
441
 
455
442
  if pHandle is None and nwItem.isRootType():
@@ -496,11 +483,8 @@ class _FilterTab(NFixedPage):
496
483
  self.filterOpt.addLabel(self.tr("Select Root Folders"))
497
484
  for tHandle, nwItem in SHARED.project.tree.iterRoots(None):
498
485
  if not nwItem.isInactiveClass():
499
- itemIcon = SHARED.theme.getItemIcon(
500
- nwItem.itemType, nwItem.itemClass, nwItem.itemLayout
501
- )
502
486
  self.filterOpt.addItem(
503
- itemIcon, nwItem.itemName, f"root:{tHandle}",
487
+ nwItem.getMainIcon(), nwItem.itemName, f"root:{tHandle}",
504
488
  default=self._build.isRootAllowed(tHandle)
505
489
  )
506
490
 
@@ -964,15 +948,6 @@ class _FormattingTab(NScrollableForm):
964
948
  spW = 6*SHARED.theme.textNWidth
965
949
  dbW = 8*SHARED.theme.textNWidth
966
950
 
967
- # Common Translations
968
-
969
- trW = self.tr("W:") # Width
970
- trH = self.tr("H:") # Height
971
- trT = self.tr("T:") # Top
972
- trB = self.tr("B:") # Bottom
973
- trL = self.tr("L:") # Left
974
- trR = self.tr("R:") # Right
975
-
976
951
  # Text Content
977
952
  # ============
978
953
 
@@ -1084,6 +1059,13 @@ class _FormattingTab(NScrollableForm):
1084
1059
  self._sidebar.addButton(title, section)
1085
1060
  self.addGroupLabel(title, section)
1086
1061
 
1062
+ pixT = SHARED.theme.getPixmap("margin_top", (iPx, iPx))
1063
+ pixB = SHARED.theme.getPixmap("margin_bottom", (iPx, iPx))
1064
+ pixL = SHARED.theme.getPixmap("margin_left", (iPx, iPx))
1065
+ pixR = SHARED.theme.getPixmap("margin_right", (iPx, iPx))
1066
+ pixH = SHARED.theme.getPixmap("size_height", (iPx, iPx))
1067
+ pixW = SHARED.theme.getPixmap("size_width", (iPx, iPx))
1068
+
1087
1069
  # Title
1088
1070
  self.titleMarginT = NDoubleSpinBox(self)
1089
1071
  self.titleMarginT.setFixedWidth(dbW)
@@ -1093,7 +1075,8 @@ class _FormattingTab(NScrollableForm):
1093
1075
 
1094
1076
  self.addRow(
1095
1077
  trConst(nwStyles.T_LABEL["H0"]),
1096
- [trT, self.titleMarginT, 6, trB, self.titleMarginB],
1078
+ [pixT, self.titleMarginT, 6, pixB, self.titleMarginB],
1079
+ unit="em",
1097
1080
  )
1098
1081
 
1099
1082
  # Heading 1
@@ -1105,7 +1088,8 @@ class _FormattingTab(NScrollableForm):
1105
1088
 
1106
1089
  self.addRow(
1107
1090
  trConst(nwStyles.T_LABEL["H1"]),
1108
- [trT, self.h1MarginT, 6, trB, self.h1MarginB],
1091
+ [pixT, self.h1MarginT, 6, pixB, self.h1MarginB],
1092
+ unit="em",
1109
1093
  )
1110
1094
 
1111
1095
  # Heading 2
@@ -1117,7 +1101,8 @@ class _FormattingTab(NScrollableForm):
1117
1101
 
1118
1102
  self.addRow(
1119
1103
  trConst(nwStyles.T_LABEL["H2"]),
1120
- [trT, self.h2MarginT, 6, trB, self.h2MarginB],
1104
+ [pixT, self.h2MarginT, 6, pixB, self.h2MarginB],
1105
+ unit="em",
1121
1106
  )
1122
1107
 
1123
1108
  # Heading 3
@@ -1129,7 +1114,8 @@ class _FormattingTab(NScrollableForm):
1129
1114
 
1130
1115
  self.addRow(
1131
1116
  trConst(nwStyles.T_LABEL["H3"]),
1132
- [trT, self.h3MarginT, 6, trB, self.h3MarginB],
1117
+ [pixT, self.h3MarginT, 6, pixB, self.h3MarginB],
1118
+ unit="em",
1133
1119
  )
1134
1120
 
1135
1121
  # Heading 4
@@ -1141,7 +1127,8 @@ class _FormattingTab(NScrollableForm):
1141
1127
 
1142
1128
  self.addRow(
1143
1129
  trConst(nwStyles.T_LABEL["H4"]),
1144
- [trT, self.h4MarginT, 6, trB, self.h4MarginB],
1130
+ [pixT, self.h4MarginT, 6, pixB, self.h4MarginB],
1131
+ unit="em",
1145
1132
  )
1146
1133
 
1147
1134
  # Text
@@ -1153,7 +1140,8 @@ class _FormattingTab(NScrollableForm):
1153
1140
 
1154
1141
  self.addRow(
1155
1142
  trConst(nwStyles.T_LABEL["TT"]),
1156
- [trT, self.textMarginT, 6, trB, self.textMarginB],
1143
+ [pixT, self.textMarginT, 6, pixB, self.textMarginB],
1144
+ unit="em",
1157
1145
  )
1158
1146
 
1159
1147
  # Separator
@@ -1165,7 +1153,8 @@ class _FormattingTab(NScrollableForm):
1165
1153
 
1166
1154
  self.addRow(
1167
1155
  trConst(nwStyles.T_LABEL["SP"]),
1168
- [trT, self.sepMarginT, 6, trB, self.sepMarginB],
1156
+ [pixT, self.sepMarginT, 6, pixB, self.sepMarginB],
1157
+ unit="em",
1169
1158
  )
1170
1159
 
1171
1160
  # Page Layout
@@ -1198,7 +1187,7 @@ class _FormattingTab(NScrollableForm):
1198
1187
 
1199
1188
  self.addRow(
1200
1189
  self._build.getLabel("format.pageSize"),
1201
- [self.pageSize, 6, trW, self.pageWidth, 6, trH, self.pageHeight],
1190
+ [self.pageSize, 6, pixW, self.pageWidth, 6, pixH, self.pageHeight],
1202
1191
  )
1203
1192
 
1204
1193
  # Page Margins
@@ -1216,11 +1205,11 @@ class _FormattingTab(NScrollableForm):
1216
1205
 
1217
1206
  self.addRow(
1218
1207
  self._build.getLabel("format.pageMargins"),
1219
- [trT, self.topMargin, 6, trB, self.bottomMargin],
1208
+ [pixT, self.topMargin, 6, pixB, self.bottomMargin],
1220
1209
  )
1221
1210
  self.addRow(
1222
1211
  "",
1223
- [trL, self.leftMargin, 6, trR, self.rightMargin],
1212
+ [pixL, self.leftMargin, 6, pixR, self.rightMargin],
1224
1213
  )
1225
1214
 
1226
1215
  # Open Document
@@ -1292,8 +1281,9 @@ class _FormattingTab(NScrollableForm):
1292
1281
  # Text Format
1293
1282
  # ===========
1294
1283
 
1295
- self._textFont = QFont()
1296
- self._textFont.fromString(self._build.getStr("format.textFont"))
1284
+ font = QFont()
1285
+ font.fromString(self._build.getStr("format.textFont"))
1286
+ self._textFont = fontMatcher(font)
1297
1287
 
1298
1288
  self.textFont.setText(describeFont(self._textFont))
1299
1289
  self.textFont.setCursorPosition(0)
@@ -1448,9 +1438,9 @@ class _FormattingTab(NScrollableForm):
1448
1438
  """Open the QFontDialog and set a font for the font style."""
1449
1439
  font, status = SHARED.getFont(self._textFont, CONFIG.nativeFont)
1450
1440
  if status:
1451
- self.textFont.setText(describeFont(font))
1441
+ self._textFont = fontMatcher(font)
1442
+ self.textFont.setText(describeFont(self._textFont))
1452
1443
  self.textFont.setCursorPosition(0)
1453
- self._textFont = font
1454
1444
  return
1455
1445
 
1456
1446
  @pyqtSlot(int)
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-01-18 [2.3b1] GuiNovelDetails
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2023-12-14 [2.3b1] GuiWelcome
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2019-10-20 [0.3.0] GuiWritingStats
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
novelwriter/types.py CHANGED
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-04-01 [2.4rc1]
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ from PyQt5.QtGui import (
28
28
  QColor, QFont, QPainter, QTextBlockFormat, QTextCharFormat, QTextCursor,
29
29
  QTextFormat
30
30
  )
31
- from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QSizePolicy, QStyle
31
+ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QHeaderView, QSizePolicy, QStyle
32
32
 
33
33
  # Qt Alignment Flags
34
34
 
@@ -66,7 +66,7 @@ QtNoBrush = Qt.BrushStyle.NoBrush
66
66
  QtNoPen = Qt.PenStyle.NoPen
67
67
  QtRoundCap = Qt.PenCapStyle.RoundCap
68
68
  QtSolidLine = Qt.PenStyle.SolidLine
69
- QtPaintAnitAlias = QPainter.RenderHint.Antialiasing
69
+ QtPaintAntiAlias = QPainter.RenderHint.Antialiasing
70
70
  QtMouseOver = QStyle.StateFlag.State_MouseOver
71
71
  QtSelected = QStyle.StateFlag.State_Selected
72
72
 
@@ -119,6 +119,12 @@ QtSizeIgnored = QSizePolicy.Policy.Ignored
119
119
  QtSizeMinimum = QSizePolicy.Policy.Minimum
120
120
  QtSizeMinimumExpanding = QSizePolicy.Policy.MinimumExpanding
121
121
 
122
+ # Resize Mode
123
+
124
+ QtHeaderStretch = QHeaderView.ResizeMode.Stretch
125
+ QtHeaderToContents = QHeaderView.ResizeMode.ResizeToContents
126
+ QtHeaderFixed = QHeaderView.ResizeMode.Fixed
127
+
122
128
  # Scroll Bar Policy
123
129
 
124
130
  QtScrollAlwaysOff = Qt.ScrollBarPolicy.ScrollBarAlwaysOff