novelWriter 2.7b1__py3-none-any.whl → 2.7.1__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 (81) hide show
  1. novelwriter/__init__.py +17 -4
  2. novelwriter/assets/i18n/nw_cs_CZ.qm +0 -0
  3. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  4. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  5. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  6. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  7. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  8. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  9. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  10. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  11. novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
  12. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  13. novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
  14. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  15. novelwriter/assets/i18n/project_cs_CZ.json +2 -0
  16. novelwriter/assets/i18n/project_de_DE.json +3 -1
  17. novelwriter/assets/i18n/project_en_GB.json +1 -0
  18. novelwriter/assets/i18n/project_en_US.json +2 -0
  19. novelwriter/assets/i18n/project_it_IT.json +2 -0
  20. novelwriter/assets/i18n/project_ja_JP.json +2 -0
  21. novelwriter/assets/i18n/project_nb_NO.json +2 -0
  22. novelwriter/assets/i18n/project_nn_NO.json +5 -0
  23. novelwriter/assets/i18n/project_pl_PL.json +2 -0
  24. novelwriter/assets/i18n/project_pt_BR.json +2 -0
  25. novelwriter/assets/i18n/project_ru_RU.json +2 -0
  26. novelwriter/assets/i18n/project_zh_CN.json +2 -0
  27. novelwriter/assets/icons/remix_filled.icons +1 -0
  28. novelwriter/assets/icons/remix_outline.icons +1 -0
  29. novelwriter/assets/images/splash.png +0 -0
  30. novelwriter/assets/manual.pdf +0 -0
  31. novelwriter/assets/manual_fr.pdf +0 -0
  32. novelwriter/assets/sample.zip +0 -0
  33. novelwriter/assets/syntax/snazzy.conf +3 -3
  34. novelwriter/assets/text/credits_en.htm +6 -0
  35. novelwriter/assets/themes/snazzy.conf +48 -0
  36. novelwriter/common.py +10 -1
  37. novelwriter/config.py +96 -25
  38. novelwriter/constants.py +21 -0
  39. novelwriter/core/buildsettings.py +3 -1
  40. novelwriter/core/coretools.py +41 -34
  41. novelwriter/core/docbuild.py +1 -0
  42. novelwriter/core/index.py +35 -5
  43. novelwriter/core/indexdata.py +4 -1
  44. novelwriter/core/item.py +35 -24
  45. novelwriter/core/itemmodel.py +17 -13
  46. novelwriter/core/novelmodel.py +2 -0
  47. novelwriter/core/project.py +14 -14
  48. novelwriter/core/projectdata.py +42 -24
  49. novelwriter/core/projectxml.py +17 -7
  50. novelwriter/core/sessions.py +29 -13
  51. novelwriter/core/tree.py +9 -5
  52. novelwriter/dialogs/docmerge.py +2 -1
  53. novelwriter/dialogs/docsplit.py +6 -3
  54. novelwriter/dialogs/editlabel.py +11 -8
  55. novelwriter/dialogs/preferences.py +37 -26
  56. novelwriter/dialogs/projectsettings.py +3 -0
  57. novelwriter/extensions/configlayout.py +6 -2
  58. novelwriter/extensions/switch.py +16 -15
  59. novelwriter/extensions/switchbox.py +1 -0
  60. novelwriter/formats/tokenizer.py +2 -1
  61. novelwriter/gui/doceditor.py +106 -47
  62. novelwriter/gui/noveltree.py +11 -5
  63. novelwriter/gui/outline.py +9 -1
  64. novelwriter/gui/projtree.py +1 -0
  65. novelwriter/gui/search.py +1 -0
  66. novelwriter/gui/statusbar.py +14 -6
  67. novelwriter/gui/theme.py +25 -10
  68. novelwriter/guimain.py +29 -9
  69. novelwriter/splash.py +74 -0
  70. novelwriter/tools/lipsum.py +2 -1
  71. novelwriter/tools/manuscript.py +1 -1
  72. novelwriter/tools/manussettings.py +52 -20
  73. novelwriter/tools/noveldetails.py +9 -8
  74. novelwriter/tools/welcome.py +1 -0
  75. novelwriter/tools/writingstats.py +68 -45
  76. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/METADATA +2 -2
  77. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/RECORD +81 -78
  78. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/WHEEL +1 -1
  79. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/entry_points.txt +0 -0
  80. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/licenses/LICENSE.md +0 -0
  81. {novelwriter-2.7b1.dist-info → novelwriter-2.7.1.dist-info}/top_level.txt +0 -0
novelwriter/splash.py ADDED
@@ -0,0 +1,74 @@
1
+ """
2
+ novelWriter – Splash Screen
3
+ ===========================
4
+
5
+ File History:
6
+ Created: 2015-04-25 [2.7rc1]
7
+
8
+ This file is a part of novelWriter
9
+ Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors
10
+
11
+ This program is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful, but
17
+ WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
+ General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
+ """
24
+ from __future__ import annotations
25
+
26
+ import logging
27
+
28
+ from pathlib import Path
29
+ from time import sleep
30
+
31
+ from PyQt6.QtCore import QRect, Qt
32
+ from PyQt6.QtGui import QColor, QPainter, QPixmap
33
+ from PyQt6.QtWidgets import QSplashScreen
34
+
35
+ logger = logging.getLogger(__name__)
36
+
37
+ SPLASH_IMG = Path(__file__).parent / "assets" / "images" / "splash.png"
38
+
39
+
40
+ class NSplashScreen(QSplashScreen):
41
+
42
+ __slots__ = ("_color", "_rect", "_text")
43
+
44
+ def __init__(self) -> None:
45
+ super().__init__(pixmap=QPixmap(str(SPLASH_IMG)), flags=Qt.WindowType.WindowStaysOnTopHint)
46
+
47
+ logger.debug("Create: NSplashScreen")
48
+
49
+ font = self.font()
50
+ font.setPointSizeF(12.0)
51
+ self.setFont(font)
52
+ self._color = QColor(26, 52, 78)
53
+ self._rect = QRect(144, 110, 440, 30)
54
+ self._text = ""
55
+ return
56
+
57
+ def __del__(self) -> None: # pragma: no cover
58
+ logger.debug("Delete: NSplashScreen")
59
+ return
60
+
61
+ def drawContents(self, painter: QPainter) -> None:
62
+ """Draw the text message."""
63
+ painter.setPen(self._color)
64
+ painter.drawText(self._rect, Qt.AlignmentFlag.AlignLeft, self._text)
65
+ return
66
+
67
+ def showStatus(self, message: str) -> None:
68
+ """Update the status message."""
69
+ self._text = message
70
+ self.showMessage(message)
71
+ if message:
72
+ logger.info("[Splash] %s", message)
73
+ sleep(0.025)
74
+ return
@@ -75,8 +75,9 @@ class GuiLipsum(NDialog):
75
75
  self.paraCount.setMaximum(100)
76
76
  self.paraCount.setValue(5)
77
77
 
78
- self.randLabel = QLabel(self.tr("Randomise order"), self)
79
78
  self.randSwitch = NSwitch(self)
79
+ self.randLabel = QLabel(self.tr("Randomise order"), self)
80
+ self.randLabel.setBuddy(self.randSwitch)
80
81
 
81
82
  self.formBox = QGridLayout()
82
83
  self.formBox.addWidget(self.headLabel, 0, 0, 1, 2, QtAlignLeft)
@@ -630,7 +630,7 @@ class _DetailsWidget(QWidget):
630
630
  self.listView.addTopLevelItem(item)
631
631
  for key in [
632
632
  "text.includeSynopsis", "text.includeComments", "text.includeStory",
633
- "text.includeKeywords", "text.includeBodyText",
633
+ "text.includeNotes", "text.includeKeywords", "text.includeBodyText",
634
634
  ]:
635
635
  sub = QTreeWidgetItem()
636
636
  sub.setText(0, build.getLabel(key))
@@ -80,7 +80,8 @@ class GuiBuildSettings(NToolDialog):
80
80
  logger.debug("Create: GuiBuildSettings")
81
81
  self.setObjectName("GuiBuildSettings")
82
82
 
83
- self._build = build
83
+ # Make a copy of the build object
84
+ self._build = BuildSettings.fromDict(build.pack())
84
85
 
85
86
  self.setWindowTitle(self.tr("Manuscript Build Settings"))
86
87
  self.setMinimumSize(700, 400)
@@ -104,6 +105,7 @@ class GuiBuildSettings(NToolDialog):
104
105
  # SideBar
105
106
  self.sidebar = NPagedSideBar(self)
106
107
  self.sidebar.setLabelColor(SHARED.theme.helpText)
108
+ self.sidebar.setAccessibleName(self.titleLabel.text())
107
109
 
108
110
  self.sidebar.addLabel(self.tr("General"))
109
111
  self.sidebar.addButton(self.tr("Selection"), self.OPT_FILTERS)
@@ -183,6 +185,7 @@ class GuiBuildSettings(NToolDialog):
183
185
  settings.
184
186
  """
185
187
  logger.debug("Closing: GuiBuildSettings")
188
+ self._applyChanges()
186
189
  self._askToSaveBuild()
187
190
  self._saveSettings()
188
191
  event.accept()
@@ -210,11 +213,14 @@ class GuiBuildSettings(NToolDialog):
210
213
  """Handle button clicks from the dialog button box."""
211
214
  role = self.buttonBox.buttonRole(button)
212
215
  if role == QtRoleApply:
216
+ self._applyChanges()
213
217
  self._emitBuildData()
214
218
  elif role == QtRoleAccept:
219
+ self._applyChanges()
215
220
  self._emitBuildData()
216
221
  self.close()
217
222
  elif role == QtRoleReject:
223
+ self._build.resetChangedState()
218
224
  self.close()
219
225
  return
220
226
 
@@ -227,10 +233,9 @@ class GuiBuildSettings(NToolDialog):
227
233
  whether the user wants to save them.
228
234
  """
229
235
  if self._build.changed:
230
- response = SHARED.question(self.tr(
236
+ if SHARED.question(self.tr(
231
237
  "Do you want to save your changes to '{0}'?"
232
- ).format(self._build.name))
233
- if response:
238
+ ).format(self._build.name)):
234
239
  self._emitBuildData()
235
240
  self._build.resetChangedState()
236
241
  return
@@ -245,14 +250,17 @@ class GuiBuildSettings(NToolDialog):
245
250
  pOptions.setValue("GuiBuildSettings", "treeWidth", treeWidth)
246
251
  pOptions.setValue("GuiBuildSettings", "filterWidth", filterWidth)
247
252
  pOptions.saveSettings()
248
-
249
253
  return
250
254
 
251
- def _emitBuildData(self) -> None:
252
- """Assemble the build data and emit the signal."""
255
+ def _applyChanges(self) -> None:
256
+ """Apply all settings changes to the build object."""
253
257
  self._build.setName(self.editBuildName.text())
254
258
  self.optTabHeadings.saveContent()
255
259
  self.optTabFormatting.saveContent()
260
+ return
261
+
262
+ def _emitBuildData(self) -> None:
263
+ """Assemble the build data and emit the signal."""
256
264
  self.newSettingsReady.emit(self._build)
257
265
  self._build.resetChangedState()
258
266
  return
@@ -564,9 +572,10 @@ class _HeadingsTab(NScrollablePage):
564
572
  self.fmtPart.setReadOnly(True)
565
573
  self.btnPart = NIconToolButton(self, iSz, "edit", "green")
566
574
  self.btnPart.clicked.connect(qtLambda(self._editHeading, self.EDIT_TITLE))
575
+ self.swtPart = NSwitch(self, height=iPx)
567
576
  self.hdePart = QLabel(trHide, self)
568
577
  self.hdePart.setIndent(6)
569
- self.swtPart = NSwitch(self, height=iPx)
578
+ self.hdePart.setBuddy(self.swtPart)
570
579
 
571
580
  self.formatBox.addWidget(self.lblPart, 0, 0)
572
581
  self.formatBox.addWidget(self.fmtPart, 0, 1)
@@ -580,9 +589,10 @@ class _HeadingsTab(NScrollablePage):
580
589
  self.fmtChapter.setReadOnly(True)
581
590
  self.btnChapter = NIconToolButton(self, iSz, "edit", "green")
582
591
  self.btnChapter.clicked.connect(qtLambda(self._editHeading, self.EDIT_CHAPTER))
592
+ self.swtChapter = NSwitch(self, height=iPx)
583
593
  self.hdeChapter = QLabel(trHide, self)
584
594
  self.hdeChapter.setIndent(6)
585
- self.swtChapter = NSwitch(self, height=iPx)
595
+ self.hdeChapter.setBuddy(self.swtChapter)
586
596
 
587
597
  self.formatBox.addWidget(self.lblChapter, 1, 0)
588
598
  self.formatBox.addWidget(self.fmtChapter, 1, 1)
@@ -596,9 +606,10 @@ class _HeadingsTab(NScrollablePage):
596
606
  self.fmtUnnumbered.setReadOnly(True)
597
607
  self.btnUnnumbered = NIconToolButton(self, iSz, "edit", "green")
598
608
  self.btnUnnumbered.clicked.connect(qtLambda(self._editHeading, self.EDIT_UNNUM))
609
+ self.swtUnnumbered = NSwitch(self, height=iPx)
599
610
  self.hdeUnnumbered = QLabel(trHide, self)
600
611
  self.hdeUnnumbered.setIndent(6)
601
- self.swtUnnumbered = NSwitch(self, height=iPx)
612
+ self.hdeUnnumbered.setBuddy(self.swtUnnumbered)
602
613
 
603
614
  self.formatBox.addWidget(self.lblUnnumbered, 2, 0)
604
615
  self.formatBox.addWidget(self.fmtUnnumbered, 2, 1)
@@ -612,9 +623,10 @@ class _HeadingsTab(NScrollablePage):
612
623
  self.fmtScene.setReadOnly(True)
613
624
  self.btnScene = NIconToolButton(self, iSz, "edit", "green")
614
625
  self.btnScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_SCENE))
626
+ self.swtScene = NSwitch(self, height=iPx)
615
627
  self.hdeScene = QLabel(trHide, self)
616
628
  self.hdeScene.setIndent(6)
617
- self.swtScene = NSwitch(self, height=iPx)
629
+ self.hdeScene.setBuddy(self.swtScene)
618
630
 
619
631
  self.formatBox.addWidget(self.lblScene, 3, 0)
620
632
  self.formatBox.addWidget(self.fmtScene, 3, 1)
@@ -628,9 +640,10 @@ class _HeadingsTab(NScrollablePage):
628
640
  self.fmtAScene.setReadOnly(True)
629
641
  self.btnAScene = NIconToolButton(self, iSz, "edit", "green")
630
642
  self.btnAScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_HSCENE))
643
+ self.swtAScene = NSwitch(self, height=iPx)
631
644
  self.hdeAScene = QLabel(trHide, self)
632
645
  self.hdeAScene.setIndent(6)
633
- self.swtAScene = NSwitch(self, height=iPx)
646
+ self.hdeAScene.setBuddy(self.swtAScene)
634
647
 
635
648
  self.formatBox.addWidget(self.lblAScene, 4, 0)
636
649
  self.formatBox.addWidget(self.fmtAScene, 4, 1)
@@ -644,9 +657,10 @@ class _HeadingsTab(NScrollablePage):
644
657
  self.fmtSection.setReadOnly(True)
645
658
  self.btnSection = NIconToolButton(self, iSz, "edit", "green")
646
659
  self.btnSection.clicked.connect(qtLambda(self._editHeading, self.EDIT_SECTION))
660
+ self.swtSection = NSwitch(self, height=iPx)
647
661
  self.hdeSection = QLabel(trHide, self)
648
662
  self.hdeSection.setIndent(6)
649
- self.swtSection = NSwitch(self, height=iPx)
663
+ self.hdeSection.setBuddy(self.swtSection)
650
664
 
651
665
  self.formatBox.addWidget(self.lblSection, 5, 0)
652
666
  self.formatBox.addWidget(self.fmtSection, 5, 1)
@@ -704,44 +718,59 @@ class _HeadingsTab(NScrollablePage):
704
718
 
705
719
  # Layout Matrix
706
720
  # =============
721
+ trCentre = self.tr("Centre")
722
+ trBreak = self.tr("Page Break")
723
+
707
724
  self.layoutMatrix = QGridLayout()
708
725
  self.layoutMatrix.setVerticalSpacing(12)
709
726
  self.layoutMatrix.setHorizontalSpacing(12)
710
727
 
711
- self.layoutMatrix.addWidget(QLabel(self.tr("Centre"), self), 0, 1)
712
- self.layoutMatrix.addWidget(QLabel(self.tr("Page Break"), self), 0, 2)
728
+ self.layoutMatrix.addWidget(QLabel(trCentre, self), 0, 1)
729
+ self.layoutMatrix.addWidget(QLabel(trBreak, self), 0, 2)
713
730
 
714
731
  # Title Layout
715
- self.lblTitle = QLabel(self._build.getLabel("headings.styleTitle"), self)
732
+ trLabel = self._build.getLabel("headings.styleTitle")
733
+ self.lblTitle = QLabel(trLabel, self)
716
734
  self.centerTitle = NSwitch(self, height=iPx)
735
+ self.centerTitle.setAccessibleName(f"{trLabel}: {trCentre}")
717
736
  self.breakTitle = NSwitch(self, height=iPx)
737
+ self.breakTitle.setAccessibleName(f"{trLabel}: {trBreak}")
718
738
 
719
739
  self.layoutMatrix.addWidget(self.lblTitle, 1, 0)
720
740
  self.layoutMatrix.addWidget(self.centerTitle, 1, 1, QtAlignCenter)
721
741
  self.layoutMatrix.addWidget(self.breakTitle, 1, 2, QtAlignCenter)
722
742
 
723
743
  # Partition Layout
724
- self.lblPart = QLabel(self._build.getLabel("headings.stylePart"), self)
744
+ trLabel = self._build.getLabel("headings.stylePart")
745
+ self.lblPart = QLabel(trLabel, self)
725
746
  self.centerPart = NSwitch(self, height=iPx)
747
+ self.centerPart.setAccessibleName(f"{trLabel}: {trCentre}")
726
748
  self.breakPart = NSwitch(self, height=iPx)
749
+ self.breakPart.setAccessibleName(f"{trLabel}: {trBreak}")
727
750
 
728
751
  self.layoutMatrix.addWidget(self.lblPart, 2, 0)
729
752
  self.layoutMatrix.addWidget(self.centerPart, 2, 1, QtAlignCenter)
730
753
  self.layoutMatrix.addWidget(self.breakPart, 2, 2, QtAlignCenter)
731
754
 
732
755
  # Chapter Layout
733
- self.lblChapter = QLabel(self._build.getLabel("headings.styleChapter"), self)
756
+ trLabel = self._build.getLabel("headings.styleChapter")
757
+ self.lblChapter = QLabel(trLabel, self)
734
758
  self.centerChapter = NSwitch(self, height=iPx)
759
+ self.centerChapter.setAccessibleName(f"{trLabel}: {trCentre}")
735
760
  self.breakChapter = NSwitch(self, height=iPx)
761
+ self.breakChapter.setAccessibleName(f"{trLabel}: {trBreak}")
736
762
 
737
763
  self.layoutMatrix.addWidget(self.lblChapter, 3, 0)
738
764
  self.layoutMatrix.addWidget(self.centerChapter, 3, 1, QtAlignCenter)
739
765
  self.layoutMatrix.addWidget(self.breakChapter, 3, 2, QtAlignCenter)
740
766
 
741
767
  # Scene Layout
742
- self.lblScene = QLabel(self._build.getLabel("headings.styleScene"), self)
768
+ trLabel = self._build.getLabel("headings.styleScene")
769
+ self.lblScene = QLabel(trLabel, self)
743
770
  self.centerScene = NSwitch(self, height=iPx)
771
+ self.centerScene.setAccessibleName(f"{trLabel}: {trCentre}")
744
772
  self.breakScene = NSwitch(self, height=iPx)
773
+ self.breakScene.setAccessibleName(f"{trLabel}: {trBreak}")
745
774
 
746
775
  self.layoutMatrix.addWidget(self.lblScene, 4, 0)
747
776
  self.layoutMatrix.addWidget(self.centerScene, 4, 1, QtAlignCenter)
@@ -952,12 +981,14 @@ class _FormattingTab(NScrollableForm):
952
981
  self.incSynopsis = NSwitch(self, height=iPx)
953
982
  self.incComments = NSwitch(self, height=iPx)
954
983
  self.incStory = NSwitch(self, height=iPx)
984
+ self.incNotes = NSwitch(self, height=iPx)
955
985
  self.incKeywords = NSwitch(self, height=iPx)
956
986
 
957
987
  self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
958
988
  self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
959
989
  self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
960
990
  self.addRow(self._build.getLabel("text.includeStory"), self.incStory)
991
+ self.addRow(self._build.getLabel("text.includeNotes"), self.incNotes)
961
992
  self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
962
993
 
963
994
  # Ignored Keywords
@@ -979,7 +1010,6 @@ class _FormattingTab(NScrollableForm):
979
1010
 
980
1011
  # Note Headings
981
1012
  self.addNoteHead = NSwitch(self, height=iPx)
982
-
983
1013
  self.addRow(self._build.getLabel("text.addNoteHeadings"), self.addNoteHead)
984
1014
 
985
1015
  # Text Format
@@ -1267,6 +1297,7 @@ class _FormattingTab(NScrollableForm):
1267
1297
  self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
1268
1298
  self.incComments.setChecked(self._build.getBool("text.includeComments"))
1269
1299
  self.incStory.setChecked(self._build.getBool("text.includeStory"))
1300
+ self.incNotes.setChecked(self._build.getBool("text.includeNotes"))
1270
1301
  self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
1271
1302
  self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
1272
1303
  self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
@@ -1366,6 +1397,7 @@ class _FormattingTab(NScrollableForm):
1366
1397
  self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
1367
1398
  self._build.setValue("text.includeComments", self.incComments.isChecked())
1368
1399
  self._build.setValue("text.includeStory", self.incStory.isChecked())
1400
+ self._build.setValue("text.includeNotes", self.incNotes.isChecked())
1369
1401
  self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
1370
1402
  self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
1371
1403
  self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
@@ -86,6 +86,7 @@ class GuiNovelDetails(NNonBlockingDialog):
86
86
  # SideBar
87
87
  self.sidebar = NPagedSideBar(self)
88
88
  self.sidebar.setLabelColor(SHARED.theme.helpText)
89
+ self.sidebar.setAccessibleName(self.titleLabel.text())
89
90
  self.sidebar.addButton(self.tr("Overview"), self.PAGE_OVERVIEW)
90
91
  self.sidebar.addButton(self.tr("Contents"), self.PAGE_CONTENTS)
91
92
  self.sidebar.setSelected(self.PAGE_OVERVIEW)
@@ -256,8 +257,8 @@ class _OverviewPage(NScrollablePage):
256
257
  def updateProjectData(self) -> None:
257
258
  """Load information about the project."""
258
259
  project = SHARED.project
259
- project.updateWordCounts()
260
- wcNovel, wcNotes = project.data.currCounts
260
+ project.updateCounts()
261
+ wcNovel, wcNotes, _, _ = project.data.currCounts
261
262
 
262
263
  self.projName.setText(project.data.name)
263
264
  self.projRevisions.setText(f"{project.data.saveCount:n}")
@@ -356,16 +357,14 @@ class _ContentsPage(NFixedPage):
356
357
  countFrom = options.getInt("GuiNovelDetails", "countFrom", 1)
357
358
  clearDouble = options.getBool("GuiNovelDetails", "clearDouble", True)
358
359
 
359
- self.wpLabel = QLabel(self.tr("Words per page"), self)
360
-
361
360
  self.wpValue = QSpinBox(self)
362
361
  self.wpValue.setMinimum(10)
363
362
  self.wpValue.setMaximum(1000)
364
363
  self.wpValue.setSingleStep(10)
365
364
  self.wpValue.setValue(wordsPerPage)
366
365
  self.wpValue.valueChanged.connect(self._populateTree)
367
-
368
- self.poLabel = QLabel(self.tr("First page offset"), self)
366
+ self.wpLabel = QLabel(self.tr("Words per page"), self)
367
+ self.wpLabel.setBuddy(self.wpValue)
369
368
 
370
369
  self.poValue = QSpinBox(self)
371
370
  self.poValue.setMinimum(1)
@@ -373,12 +372,14 @@ class _ContentsPage(NFixedPage):
373
372
  self.poValue.setSingleStep(1)
374
373
  self.poValue.setValue(countFrom)
375
374
  self.poValue.valueChanged.connect(self._populateTree)
376
-
377
- self.dblLabel = QLabel(self.tr("Chapters on odd pages"), self)
375
+ self.poLabel = QLabel(self.tr("First page offset"), self)
376
+ self.poLabel.setBuddy(self.poValue)
378
377
 
379
378
  self.dblValue = NSwitch(self, height=iPx)
380
379
  self.dblValue.setChecked(clearDouble)
381
380
  self.dblValue.clicked.connect(self._populateTree)
381
+ self.dblLabel = QLabel(self.tr("Chapters on odd pages"), self)
382
+ self.dblLabel.setBuddy(self.dblValue)
382
383
 
383
384
  self.optionsBox = QGridLayout()
384
385
  self.optionsBox.addWidget(self.wpLabel, 0, 0)
@@ -565,6 +565,7 @@ class _NewProjectForm(QWidget):
565
565
  self.projAuthor = QLineEdit(self)
566
566
  self.projAuthor.setMaxLength(200)
567
567
  self.projAuthor.setPlaceholderText(self.tr("Optional"))
568
+ self.projAuthor.setText(CONFIG.lastAuthor)
568
569
 
569
570
  # Project Path
570
571
  self.projPath = QLineEdit(self)
@@ -183,59 +183,82 @@ class GuiWritingStats(NToolDialog):
183
183
  # Filter Options
184
184
  iPx = SHARED.theme.baseIconHeight
185
185
 
186
- self.filterBox = QGroupBox(self.tr("Filters"), self)
187
186
  self.filterForm = QGridLayout(self)
187
+ self.filterForm.setRowStretch(6, 1)
188
+ self.filterBox = QGroupBox(self.tr("Filters"), self)
188
189
  self.filterBox.setLayout(self.filterForm)
189
190
 
190
- self.incNovel = NSwitch(self, height=iPx)
191
- self.incNovel.setChecked(
191
+ # Include Novel Files
192
+ self.swtIncNovel = NSwitch(self, height=iPx)
193
+ self.swtIncNovel.setChecked(
192
194
  pOptions.getBool("GuiWritingStats", "incNovel", True)
193
195
  )
194
- self.incNovel.clicked.connect(self._updateListBox)
196
+ self.swtIncNovel.clicked.connect(self._updateListBox)
197
+ self.lblIncNovel = QLabel(self.tr("Count novel files"), self)
198
+ self.lblIncNovel.setBuddy(self.swtIncNovel)
195
199
 
196
- self.incNotes = NSwitch(self, height=iPx)
197
- self.incNotes.setChecked(
200
+ self.filterForm.addWidget(self.lblIncNovel, 0, 0)
201
+ self.filterForm.addWidget(self.swtIncNovel, 0, 1)
202
+
203
+ # Include Note Files
204
+ self.swtIncNotes = NSwitch(self, height=iPx)
205
+ self.swtIncNotes.setChecked(
198
206
  pOptions.getBool("GuiWritingStats", "incNotes", True)
199
207
  )
200
- self.incNotes.clicked.connect(self._updateListBox)
208
+ self.swtIncNotes.clicked.connect(self._updateListBox)
209
+ self.lblIncNotes = QLabel(self.tr("Count note files"), self)
210
+ self.lblIncNotes.setBuddy(self.swtIncNotes)
211
+
212
+ self.filterForm.addWidget(self.lblIncNotes, 1, 0)
213
+ self.filterForm.addWidget(self.swtIncNotes, 1, 1)
201
214
 
202
- self.hideZeros = NSwitch(self, height=iPx)
203
- self.hideZeros.setChecked(
215
+ # Hide Zero Counts
216
+ self.swtHideZeros = NSwitch(self, height=iPx)
217
+ self.swtHideZeros.setChecked(
204
218
  pOptions.getBool("GuiWritingStats", "hideZeros", True)
205
219
  )
206
- self.hideZeros.clicked.connect(self._updateListBox)
220
+ self.swtHideZeros.clicked.connect(self._updateListBox)
221
+ self.lblHideZeros = QLabel(self.tr("Hide zero word count"), self)
222
+ self.lblHideZeros.setBuddy(self.swtHideZeros)
207
223
 
208
- self.hideNegative = NSwitch(self, height=iPx)
209
- self.hideNegative.setChecked(
224
+ self.filterForm.addWidget(self.lblHideZeros, 2, 0)
225
+ self.filterForm.addWidget(self.swtHideZeros, 2, 1)
226
+
227
+ # Hide Negative Counts
228
+ self.swtHideNegative = NSwitch(self, height=iPx)
229
+ self.swtHideNegative.setChecked(
210
230
  pOptions.getBool("GuiWritingStats", "hideNegative", False)
211
231
  )
212
- self.hideNegative.clicked.connect(self._updateListBox)
232
+ self.swtHideNegative.clicked.connect(self._updateListBox)
233
+ self.lblHideNegative = QLabel(self.tr("Hide negative word count"), self)
234
+ self.lblHideNegative.setBuddy(self.swtHideNegative)
235
+
236
+ self.filterForm.addWidget(self.lblHideNegative, 3, 0)
237
+ self.filterForm.addWidget(self.swtHideNegative, 3, 1)
213
238
 
214
- self.groupByDay = NSwitch(self, height=iPx)
215
- self.groupByDay.setChecked(
239
+ # Group Entries
240
+ self.swtGroupByDay = NSwitch(self, height=iPx)
241
+ self.swtGroupByDay.setChecked(
216
242
  pOptions.getBool("GuiWritingStats", "groupByDay", False)
217
243
  )
218
- self.groupByDay.clicked.connect(self._updateListBox)
244
+ self.swtGroupByDay.clicked.connect(self._updateListBox)
245
+ self.lblGroupByDay = QLabel(self.tr("Group entries by day"), self)
246
+ self.lblGroupByDay.setBuddy(self.swtGroupByDay)
247
+
248
+ self.filterForm.addWidget(self.lblGroupByDay, 4, 0)
249
+ self.filterForm.addWidget(self.swtGroupByDay, 4, 1)
219
250
 
220
- self.showIdleTime = NSwitch(self, height=iPx)
221
- self.showIdleTime.setChecked(
251
+ # Show Idle
252
+ self.swtShowIdleTime = NSwitch(self, height=iPx)
253
+ self.swtShowIdleTime.setChecked(
222
254
  pOptions.getBool("GuiWritingStats", "showIdleTime", False)
223
255
  )
224
- self.showIdleTime.clicked.connect(self._updateListBox)
225
-
226
- self.filterForm.addWidget(QLabel(self.tr("Count novel files"), self), 0, 0)
227
- self.filterForm.addWidget(QLabel(self.tr("Count note files"), self), 1, 0)
228
- self.filterForm.addWidget(QLabel(self.tr("Hide zero word count"), self), 2, 0)
229
- self.filterForm.addWidget(QLabel(self.tr("Hide negative word count"), self), 3, 0)
230
- self.filterForm.addWidget(QLabel(self.tr("Group entries by day"), self), 4, 0)
231
- self.filterForm.addWidget(QLabel(self.tr("Show idle time"), self), 5, 0)
232
- self.filterForm.addWidget(self.incNovel, 0, 1)
233
- self.filterForm.addWidget(self.incNotes, 1, 1)
234
- self.filterForm.addWidget(self.hideZeros, 2, 1)
235
- self.filterForm.addWidget(self.hideNegative, 3, 1)
236
- self.filterForm.addWidget(self.groupByDay, 4, 1)
237
- self.filterForm.addWidget(self.showIdleTime, 5, 1)
238
- self.filterForm.setRowStretch(6, 1)
256
+ self.swtShowIdleTime.clicked.connect(self._updateListBox)
257
+ self.lblShowIdleTime = QLabel(self.tr("Show idle time"), self)
258
+ self.lblShowIdleTime.setBuddy(self.swtShowIdleTime)
259
+
260
+ self.filterForm.addWidget(self.lblShowIdleTime, 5, 0)
261
+ self.filterForm.addWidget(self.swtShowIdleTime, 5, 1)
239
262
 
240
263
  # Settings
241
264
  self.histMax = QSpinBox(self)
@@ -325,12 +348,12 @@ class GuiWritingStats(NToolDialog):
325
348
 
326
349
  sortCol = self.listBox.sortColumn()
327
350
  sortOrder = header.sortIndicatorOrder() if header else 0
328
- incNovel = self.incNovel.isChecked()
329
- incNotes = self.incNotes.isChecked()
330
- hideZeros = self.hideZeros.isChecked()
331
- hideNegative = self.hideNegative.isChecked()
332
- groupByDay = self.groupByDay.isChecked()
333
- showIdleTime = self.showIdleTime.isChecked()
351
+ incNovel = self.swtIncNovel.isChecked()
352
+ incNotes = self.swtIncNotes.isChecked()
353
+ hideZeros = self.swtHideZeros.isChecked()
354
+ hideNegative = self.swtHideNegative.isChecked()
355
+ groupByDay = self.swtGroupByDay.isChecked()
356
+ showIdleTime = self.swtShowIdleTime.isChecked()
334
357
  histMax = self.histMax.value()
335
358
 
336
359
  logger.debug("Saving State: GuiWritingStats")
@@ -487,11 +510,11 @@ class GuiWritingStats(NToolDialog):
487
510
  self.listBox.clear()
488
511
  self.timeFilter = 0.0
489
512
 
490
- incNovel = self.incNovel.isChecked()
491
- incNotes = self.incNotes.isChecked()
492
- hideZeros = self.hideZeros.isChecked()
493
- hideNegative = self.hideNegative.isChecked()
494
- groupByDay = self.groupByDay.isChecked()
513
+ incNovel = self.swtIncNovel.isChecked()
514
+ incNotes = self.swtIncNotes.isChecked()
515
+ hideZeros = self.swtHideZeros.isChecked()
516
+ hideNegative = self.swtHideNegative.isChecked()
517
+ groupByDay = self.swtGroupByDay.isChecked()
495
518
  histMax = self.histMax.value()
496
519
 
497
520
  # Group the data
@@ -563,7 +586,7 @@ class GuiWritingStats(NToolDialog):
563
586
  # Populate the list
564
587
  mTrans = Qt.TransformationMode.FastTransformation
565
588
  mAspect = Qt.AspectRatioMode.IgnoreAspectRatio
566
- showIdleTime = self.showIdleTime.isChecked()
589
+ showIdleTime = self.swtShowIdleTime.isChecked()
567
590
  for _, sStart, sDiff, nWords, _, _, sIdle in self.filterData:
568
591
 
569
592
  if showIdleTime:
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: novelWriter
3
- Version: 2.7b1
4
- Summary: A markdown-like text editor for planning and writing novels
3
+ Version: 2.7.1
4
+ Summary: A plain text editor for planning and writing novels
5
5
  Author-email: Veronica Berglyd Olsen <code@vkbo.net>
6
6
  License: GNU General Public License v3
7
7
  Project-URL: Homepage, https://novelwriter.io