novelWriter 2.5.1__py3-none-any.whl → 2.6b1__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 (64) hide show
  1. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/METADATA +2 -1
  2. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/RECORD +61 -56
  3. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +3 -3
  5. novelwriter/assets/i18n/project_en_GB.json +1 -0
  6. novelwriter/assets/icons/typicons_dark/icons.conf +1 -0
  7. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +1 -0
  9. novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
  10. novelwriter/assets/manual.pdf +0 -0
  11. novelwriter/assets/sample.zip +0 -0
  12. novelwriter/assets/themes/default_light.conf +2 -2
  13. novelwriter/common.py +63 -0
  14. novelwriter/config.py +10 -3
  15. novelwriter/constants.py +153 -60
  16. novelwriter/core/buildsettings.py +66 -39
  17. novelwriter/core/coretools.py +34 -22
  18. novelwriter/core/docbuild.py +130 -169
  19. novelwriter/core/index.py +29 -18
  20. novelwriter/core/item.py +2 -2
  21. novelwriter/core/options.py +4 -1
  22. novelwriter/core/spellcheck.py +9 -14
  23. novelwriter/dialogs/preferences.py +45 -32
  24. novelwriter/dialogs/projectsettings.py +3 -3
  25. novelwriter/enum.py +29 -23
  26. novelwriter/extensions/configlayout.py +24 -11
  27. novelwriter/extensions/modified.py +13 -1
  28. novelwriter/extensions/pagedsidebar.py +5 -5
  29. novelwriter/formats/shared.py +155 -0
  30. novelwriter/formats/todocx.py +1195 -0
  31. novelwriter/formats/tohtml.py +452 -0
  32. novelwriter/{core → formats}/tokenizer.py +483 -485
  33. novelwriter/formats/tomarkdown.py +217 -0
  34. novelwriter/{core → formats}/toodt.py +270 -320
  35. novelwriter/formats/toqdoc.py +436 -0
  36. novelwriter/formats/toraw.py +91 -0
  37. novelwriter/gui/doceditor.py +240 -193
  38. novelwriter/gui/dochighlight.py +96 -84
  39. novelwriter/gui/docviewer.py +56 -30
  40. novelwriter/gui/docviewerpanel.py +3 -3
  41. novelwriter/gui/editordocument.py +17 -2
  42. novelwriter/gui/itemdetails.py +8 -4
  43. novelwriter/gui/mainmenu.py +121 -60
  44. novelwriter/gui/noveltree.py +35 -37
  45. novelwriter/gui/outline.py +186 -238
  46. novelwriter/gui/projtree.py +142 -131
  47. novelwriter/gui/sidebar.py +7 -6
  48. novelwriter/gui/theme.py +5 -4
  49. novelwriter/guimain.py +43 -155
  50. novelwriter/shared.py +14 -4
  51. novelwriter/text/counting.py +2 -0
  52. novelwriter/text/patterns.py +155 -59
  53. novelwriter/tools/manusbuild.py +1 -1
  54. novelwriter/tools/manuscript.py +121 -78
  55. novelwriter/tools/manussettings.py +403 -260
  56. novelwriter/tools/welcome.py +4 -4
  57. novelwriter/tools/writingstats.py +3 -3
  58. novelwriter/types.py +16 -6
  59. novelwriter/core/tohtml.py +0 -530
  60. novelwriter/core/tomarkdown.py +0 -252
  61. novelwriter/core/toqdoc.py +0 -419
  62. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/LICENSE.md +0 -0
  63. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/entry_points.txt +0 -0
  64. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/top_level.txt +0 -0
@@ -29,7 +29,10 @@ from time import time
29
29
  from typing import TYPE_CHECKING
30
30
 
31
31
  from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
32
- from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent, QTextDocument
32
+ from PyQt5.QtGui import (
33
+ QCloseEvent, QColor, QCursor, QDesktopServices, QFont, QPalette,
34
+ QResizeEvent, QTextDocument
35
+ )
33
36
  from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
34
37
  from PyQt5.QtWidgets import (
35
38
  QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
@@ -40,12 +43,14 @@ from PyQt5.QtWidgets import (
40
43
 
41
44
  from novelwriter import CONFIG, SHARED
42
45
  from novelwriter.common import fuzzyTime
46
+ from novelwriter.constants import nwLabels, nwStats, trConst
43
47
  from novelwriter.core.buildsettings import BuildCollection, BuildSettings
44
48
  from novelwriter.core.docbuild import NWBuildDocument
45
- from novelwriter.core.tokenizer import HeadingFormatter
46
- from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
47
49
  from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton, NToolDialog
48
50
  from novelwriter.extensions.progressbars import NProgressCircle
51
+ from novelwriter.extensions.switch import NSwitch
52
+ from novelwriter.formats.tokenizer import HeadingFormatter
53
+ from novelwriter.formats.toqdoc import ToQTextDocument
49
54
  from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
50
55
  from novelwriter.tools.manusbuild import GuiManuscriptBuild
51
56
  from novelwriter.tools.manussettings import GuiBuildSettings
@@ -83,6 +88,7 @@ class GuiManuscript(NToolDialog):
83
88
  self.setMinimumWidth(CONFIG.pxInt(600))
84
89
  self.setMinimumHeight(CONFIG.pxInt(500))
85
90
 
91
+ iPx = SHARED.theme.baseIconHeight
86
92
  iSz = SHARED.theme.baseIconSize
87
93
  wWin = CONFIG.pxInt(900)
88
94
  hWin = CONFIG.pxInt(600)
@@ -112,6 +118,11 @@ class GuiManuscript(NToolDialog):
112
118
  self.tbDel.setStyleSheet(buttonStyle)
113
119
  self.tbDel.clicked.connect(self._deleteSelectedBuild)
114
120
 
121
+ self.tbCopy = NIconToolButton(self, iSz, "copy")
122
+ self.tbCopy.setToolTip(self.tr("Duplicate Selected Build"))
123
+ self.tbCopy.setStyleSheet(buttonStyle)
124
+ self.tbCopy.clicked.connect(self._copySelectedBuild)
125
+
115
126
  self.tbEdit = NIconToolButton(self, iSz, "edit")
116
127
  self.tbEdit.setToolTip(self.tr("Edit Selected Build"))
117
128
  self.tbEdit.setStyleSheet(buttonStyle)
@@ -124,6 +135,7 @@ class GuiManuscript(NToolDialog):
124
135
  self.listToolBox.addStretch(1)
125
136
  self.listToolBox.addWidget(self.tbAdd)
126
137
  self.listToolBox.addWidget(self.tbDel)
138
+ self.listToolBox.addWidget(self.tbCopy)
127
139
  self.listToolBox.addWidget(self.tbEdit)
128
140
  self.listToolBox.setSpacing(0)
129
141
 
@@ -181,15 +193,31 @@ class GuiManuscript(NToolDialog):
181
193
  self.processBox.addWidget(self.btnBuild, 1, 0)
182
194
  self.processBox.addWidget(self.btnClose, 1, 1)
183
195
 
196
+ # Preview Options
197
+ # ===============
198
+
199
+ self.swtNewPage = NSwitch(self, height=iPx)
200
+ self.swtNewPage.setChecked(pOptions.getBool("GuiManuscript", "showNewPage", True))
201
+ self.swtNewPage.clicked.connect(self._generatePreview)
202
+
203
+ self.lblNewPage = QLabel(self.tr("Show Page Breaks"), self)
204
+ self.lblNewPage.setBuddy(self.swtNewPage)
205
+
184
206
  # Assemble GUI
185
207
  # ============
186
208
 
187
209
  self.docPreview = _PreviewWidget(self)
188
210
  self.docStats = _StatsWidget(self)
189
211
 
212
+ self.docBar = QHBoxLayout()
213
+ self.docBar.addWidget(self.docStats, 1, QtAlignTop)
214
+ self.docBar.addWidget(self.lblNewPage, 0, QtAlignTop)
215
+ self.docBar.addWidget(self.swtNewPage, 0, QtAlignTop)
216
+ self.docBar.setContentsMargins(0, 0, 0, 0)
217
+
190
218
  self.docBox = QVBoxLayout()
191
219
  self.docBox.addWidget(self.docPreview, 1)
192
- self.docBox.addWidget(self.docStats, 0)
220
+ self.docBox.addLayout(self.docBar, 0)
193
221
  self.docBox.setContentsMargins(0, 0, 0, 0)
194
222
 
195
223
  self.docWdiget = QWidget(self)
@@ -287,6 +315,17 @@ class GuiManuscript(NToolDialog):
287
315
  self._openSettingsDialog(build)
288
316
  return
289
317
 
318
+ @pyqtSlot()
319
+ def _copySelectedBuild(self) -> None:
320
+ """Copy the currently selected build settings entry."""
321
+ if build := self._getSelectedBuild():
322
+ new = BuildSettings.duplicate(build)
323
+ self._builds.setBuild(new)
324
+ self._updateBuildsList()
325
+ if item := self._buildMap.get(new.buildID):
326
+ item.setSelected(True)
327
+ return
328
+
290
329
  @pyqtSlot("QListWidgetItem*", "QListWidgetItem*")
291
330
  def _updateBuildDetails(self, current: QListWidgetItem, previous: QListWidgetItem) -> None:
292
331
  """Process change of build selection to update the details."""
@@ -323,6 +362,7 @@ class GuiManuscript(NToolDialog):
323
362
  return
324
363
 
325
364
  start = time()
365
+ showNewPage = self.swtNewPage.isChecked()
326
366
 
327
367
  # Make sure editor content is saved before we start
328
368
  SHARED.saveEditor()
@@ -330,22 +370,8 @@ class GuiManuscript(NToolDialog):
330
370
  docBuild = NWBuildDocument(SHARED.project, build)
331
371
  docBuild.queueAll()
332
372
 
333
- theme = TextDocumentTheme()
334
- theme.text = QColor(0, 0, 0)
335
- theme.highlight = QColor(255, 255, 166)
336
- theme.head = QColor(66, 113, 174)
337
- theme.comment = QColor(100, 100, 100)
338
- theme.note = QColor(129, 55, 9)
339
- theme.code = QColor(66, 113, 174)
340
- theme.modifier = QColor(129, 55, 9)
341
- theme.keyword = QColor(245, 135, 31)
342
- theme.tag = QColor(66, 113, 174)
343
- theme.optional = QColor(66, 113, 174)
344
- theme.dialog = QColor(66, 113, 174)
345
- theme.altdialog = QColor(129, 55, 9)
346
-
347
373
  self.docPreview.beginNewBuild(len(docBuild))
348
- for step, _ in docBuild.iterBuildPreview(theme):
374
+ for step, _ in docBuild.iterBuildPreview(showNewPage):
349
375
  self.docPreview.buildStep(step + 1)
350
376
  QApplication.processEvents()
351
377
 
@@ -427,6 +453,7 @@ class GuiManuscript(NToolDialog):
427
453
  detailsHeight = CONFIG.rpxInt(buildSplit[1])
428
454
  detailsWidth = CONFIG.rpxInt(self.buildDetails.getColumnWidth())
429
455
  detailsExpanded = self.buildDetails.getExpandedState()
456
+ showNewPage = self.swtNewPage.isChecked()
430
457
 
431
458
  logger.debug("Saving State: GuiManuscript")
432
459
  pOptions = SHARED.project.options
@@ -438,6 +465,7 @@ class GuiManuscript(NToolDialog):
438
465
  pOptions.setValue("GuiManuscript", "detailsHeight", detailsHeight)
439
466
  pOptions.setValue("GuiManuscript", "detailsWidth", detailsWidth)
440
467
  pOptions.setValue("GuiManuscript", "detailsExpanded", detailsExpanded)
468
+ pOptions.setValue("GuiManuscript", "showNewPage", showNewPage)
441
469
  pOptions.saveSettings()
442
470
 
443
471
  return
@@ -470,9 +498,8 @@ class GuiManuscript(NToolDialog):
470
498
 
471
499
  def _updateBuildItem(self, build: BuildSettings) -> None:
472
500
  """Update the entry of a specific build item."""
473
- bItem = self._buildMap.get(build.buildID, None)
474
- if isinstance(bItem, QListWidgetItem):
475
- bItem.setText(build.name)
501
+ if item := self._buildMap.get(build.buildID):
502
+ item.setText(build.name)
476
503
  else: # Probably a new item
477
504
  self._updateBuildsList()
478
505
  return
@@ -593,7 +620,7 @@ class _DetailsWidget(QWidget):
593
620
  item.setText(1, "")
594
621
  self.listView.addTopLevelItem(item)
595
622
  for hFormat, hHide in [
596
- ("headings.fmtTitle", "headings.hideTitle"),
623
+ ("headings.fmtPart", "headings.hidePart"),
597
624
  ("headings.fmtChapter", "headings.hideChapter"),
598
625
  ("headings.fmtUnnumbered", "headings.hideUnnumbered"),
599
626
  ("headings.fmtScene", "headings.hideScene"),
@@ -725,6 +752,7 @@ class _PreviewWidget(QTextBrowser):
725
752
  self.setMinimumWidth(40*SHARED.theme.textNWidth)
726
753
  self.setTabStopDistance(CONFIG.getTabWidth())
727
754
  self.setOpenExternalLinks(False)
755
+ self.setOpenLinks(False)
728
756
 
729
757
  self.document().setDocumentMargin(CONFIG.getTextMargin())
730
758
  self.setPlaceholderText(self.tr(
@@ -733,6 +761,9 @@ class _PreviewWidget(QTextBrowser):
733
761
 
734
762
  self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
735
763
 
764
+ # Signals
765
+ self.anchorClicked.connect(self._linkClicked)
766
+
736
767
  # Document Age
737
768
  aPalette = self.palette()
738
769
  aPalette.setColor(QPalette.ColorRole.Window, aPalette.toolTipBase().color())
@@ -823,6 +854,7 @@ class _PreviewWidget(QTextBrowser):
823
854
 
824
855
  document.setDocumentMargin(CONFIG.getTextMargin())
825
856
  self.setDocument(document)
857
+ self.setTabStopDistance(CONFIG.getTabWidth())
826
858
 
827
859
  self._docTime = int(time())
828
860
  self._updateBuildAge()
@@ -868,6 +900,17 @@ class _PreviewWidget(QTextBrowser):
868
900
  # Private Slots
869
901
  ##
870
902
 
903
+ @pyqtSlot("QUrl")
904
+ def _linkClicked(self, url: QUrl) -> None:
905
+ """Process a clicked link in the document."""
906
+ if link := url.url():
907
+ logger.debug("Clicked link: '%s'", link)
908
+ if link.startswith("#"):
909
+ self.navigateTo(link.lstrip("#"))
910
+ elif link.startswith("http"):
911
+ QDesktopServices.openUrl(QUrl(url))
912
+ return
913
+
871
914
  @pyqtSlot()
872
915
  def _updateBuildAge(self) -> None:
873
916
  """Update the build time and the fuzzy age."""
@@ -923,8 +966,7 @@ class _StatsWidget(QWidget):
923
966
  self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize, "unfold")
924
967
  self.toggleButton.toggled.connect(self._toggleView)
925
968
 
926
- self._buildMinimal()
927
- self._buildMaximal()
969
+ self._buildBottomPanel()
928
970
 
929
971
  self.mainStack = QStackedWidget(self)
930
972
  self.mainStack.addWidget(self.minWidget)
@@ -944,23 +986,23 @@ class _StatsWidget(QWidget):
944
986
  def updateStats(self, data: dict[str, int]) -> None:
945
987
  """Update the stats values from a Tokenizer stats dict."""
946
988
  # Minimal
947
- self.minWordCount.setText("{0:n}".format(data.get("allWords", 0)))
948
- self.minCharCount.setText("{0:n}".format(data.get("allChars", 0)))
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)))
949
991
 
950
992
  # Maximal
951
- self.maxTotalWords.setText("{0:n}".format(data.get("allWords", 0)))
952
- self.maxHeadWords.setText("{0:n}".format(data.get("titleWords", 0)))
953
- self.maxTextWords.setText("{0:n}".format(data.get("textWords", 0)))
954
- self.maxTitleCount.setText("{0:n}".format(data.get("titleCount", 0)))
955
- self.maxParCount.setText("{0:n}".format(data.get("paragraphCount", 0)))
993
+ self.maxTotalWords.setText("{0:n}".format(data.get(nwStats.WORDS_ALL, 0)))
994
+ self.maxHeadWords.setText("{0:n}".format(data.get(nwStats.WORDS_TITLE, 0)))
995
+ self.maxTextWords.setText("{0:n}".format(data.get(nwStats.WORDS_TEXT, 0)))
996
+ self.maxTitleCount.setText("{0:n}".format(data.get(nwStats.TITLES, 0)))
997
+ self.maxParCount.setText("{0:n}".format(data.get(nwStats.PARAGRAPHS, 0)))
956
998
 
957
- self.maxTotalChars.setText("{0:n}".format(data.get("allChars", 0)))
958
- self.maxHeaderChars.setText("{0:n}".format(data.get("titleChars", 0)))
959
- self.maxTextChars.setText("{0:n}".format(data.get("textChars", 0)))
999
+ self.maxTotalChars.setText("{0:n}".format(data.get(nwStats.CHARS_ALL, 0)))
1000
+ self.maxHeaderChars.setText("{0:n}".format(data.get(nwStats.CHARS_TITLE, 0)))
1001
+ self.maxTextChars.setText("{0:n}".format(data.get(nwStats.CHARS_TEXT, 0)))
960
1002
 
961
- self.maxTotalWordChars.setText("{0:n}".format(data.get("allWordChars", 0)))
962
- self.maxHeadWordChars.setText("{0:n}".format(data.get("titleWordChars", 0)))
963
- self.maxTextWordChars.setText("{0:n}".format(data.get("textWordChars", 0)))
1003
+ self.maxTotalWordChars.setText("{0:n}".format(data.get(nwStats.WCHARS_ALL, 0)))
1004
+ self.maxHeadWordChars.setText("{0:n}".format(data.get(nwStats.WCHARS_TITLE, 0)))
1005
+ self.maxTextWordChars.setText("{0:n}".format(data.get(nwStats.WCHARS_TEXT, 0)))
964
1006
 
965
1007
  return
966
1008
 
@@ -989,37 +1031,29 @@ class _StatsWidget(QWidget):
989
1031
  # Internal Functions
990
1032
  ##
991
1033
 
992
- def _buildMinimal(self) -> None:
993
- """Build the minimal stats page."""
1034
+ def _buildBottomPanel(self) -> None:
1035
+ """Build the bottom page."""
994
1036
  mPx = CONFIG.pxInt(8)
1037
+ hPx = CONFIG.pxInt(12)
1038
+ vPx = CONFIG.pxInt(4)
995
1039
 
996
- self.lblWordCount = QLabel(self.tr("Words"), self)
1040
+ trAllChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_ALL])
1041
+ trTextChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_TEXT])
1042
+ trTitleChars = trConst(nwLabels.STATS_NAME[nwStats.CHARS_TITLE])
1043
+ trParagraphCount = trConst(nwLabels.STATS_NAME[nwStats.PARAGRAPHS])
1044
+ trTitleCount = trConst(nwLabels.STATS_NAME[nwStats.TITLES])
1045
+ trAllWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_ALL])
1046
+ trTextWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_TEXT])
1047
+ trTitleWordChars = trConst(nwLabels.STATS_NAME[nwStats.WCHARS_TITLE])
1048
+ trAllWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_ALL])
1049
+ trTextWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_TEXT])
1050
+ trTitleWords = trConst(nwLabels.STATS_NAME[nwStats.WORDS_TITLE])
1051
+
1052
+ # Minimal Form
997
1053
  self.minWordCount = QLabel(self)
998
-
999
- self.lblCharCount = QLabel(self.tr("Characters"), self)
1000
1054
  self.minCharCount = QLabel(self)
1001
1055
 
1002
- # Assemble
1003
- self.minLayout = QHBoxLayout()
1004
- self.minLayout.addWidget(self.lblWordCount)
1005
- self.minLayout.addWidget(self.minWordCount)
1006
- self.minLayout.addSpacing(mPx)
1007
- self.minLayout.addWidget(self.lblCharCount)
1008
- self.minLayout.addWidget(self.minCharCount)
1009
- self.minLayout.addStretch(1)
1010
- self.minLayout.setSpacing(mPx)
1011
- self.minLayout.setContentsMargins(0, 0, 0, 0)
1012
-
1013
- self.minWidget.setLayout(self.minLayout)
1014
-
1015
- return
1016
-
1017
- def _buildMaximal(self) -> None:
1018
- """Build the maximal stats page."""
1019
- hPx = CONFIG.pxInt(12)
1020
- vPx = CONFIG.pxInt(4)
1021
-
1022
- # Left Column
1056
+ # Maximal Form, Left Column
1023
1057
  self.maxTotalWords = QLabel(self)
1024
1058
  self.maxHeadWords = QLabel(self)
1025
1059
  self.maxTextWords = QLabel(self)
@@ -1033,20 +1067,19 @@ class _StatsWidget(QWidget):
1033
1067
  self.maxParCount.setAlignment(QtAlignRight)
1034
1068
 
1035
1069
  self.leftForm = QFormLayout()
1036
- self.leftForm.addRow(self.tr("Words"), self.maxTotalWords)
1037
- self.leftForm.addRow(self.tr("Words in Headings"), self.maxHeadWords)
1038
- self.leftForm.addRow(self.tr("Words in Text"), self.maxTextWords)
1070
+ self.leftForm.addRow(trAllWords, self.maxTotalWords)
1071
+ self.leftForm.addRow(trTitleWords, self.maxHeadWords)
1072
+ self.leftForm.addRow(trTextWords, self.maxTextWords)
1039
1073
  self.leftForm.addRow("", QLabel(self))
1040
- self.leftForm.addRow(self.tr("Headings"), self.maxTitleCount)
1041
- self.leftForm.addRow(self.tr("Paragraphs"), self.maxParCount)
1074
+ self.leftForm.addRow(trTitleCount, self.maxTitleCount)
1075
+ self.leftForm.addRow(trParagraphCount, self.maxParCount)
1042
1076
  self.leftForm.setHorizontalSpacing(hPx)
1043
1077
  self.leftForm.setVerticalSpacing(vPx)
1044
1078
 
1045
- # Right Column
1079
+ # Maximal Form, Right Column
1046
1080
  self.maxTotalChars = QLabel(self)
1047
1081
  self.maxHeaderChars = QLabel(self)
1048
1082
  self.maxTextChars = QLabel(self)
1049
-
1050
1083
  self.maxTotalWordChars = QLabel(self)
1051
1084
  self.maxHeadWordChars = QLabel(self)
1052
1085
  self.maxTextWordChars = QLabel(self)
@@ -1054,22 +1087,31 @@ class _StatsWidget(QWidget):
1054
1087
  self.maxTotalChars.setAlignment(QtAlignRight)
1055
1088
  self.maxHeaderChars.setAlignment(QtAlignRight)
1056
1089
  self.maxTextChars.setAlignment(QtAlignRight)
1057
-
1058
1090
  self.maxTotalWordChars.setAlignment(QtAlignRight)
1059
1091
  self.maxHeadWordChars.setAlignment(QtAlignRight)
1060
1092
  self.maxTextWordChars.setAlignment(QtAlignRight)
1061
1093
 
1062
1094
  self.rightForm = QFormLayout()
1063
- self.rightForm.addRow(self.tr("Characters"), self.maxTotalChars)
1064
- self.rightForm.addRow(self.tr("Characters in Headings"), self.maxHeaderChars)
1065
- self.rightForm.addRow(self.tr("Characters in Text"), self.maxTextChars)
1066
- self.rightForm.addRow(self.tr("Characters, No Spaces"), self.maxTotalWordChars)
1067
- self.rightForm.addRow(self.tr("Characters in Headings, No Spaces"), self.maxHeadWordChars)
1068
- self.rightForm.addRow(self.tr("Characters in Text, No Spaces"), self.maxTextWordChars)
1095
+ self.rightForm.addRow(trAllChars, self.maxTotalChars)
1096
+ self.rightForm.addRow(trTitleChars, self.maxHeaderChars)
1097
+ self.rightForm.addRow(trTextChars, self.maxTextChars)
1098
+ self.rightForm.addRow(trAllWordChars, self.maxTotalWordChars)
1099
+ self.rightForm.addRow(trTitleWordChars, self.maxHeadWordChars)
1100
+ self.rightForm.addRow(trTextWordChars, self.maxTextWordChars)
1069
1101
  self.rightForm.setHorizontalSpacing(hPx)
1070
1102
  self.rightForm.setVerticalSpacing(vPx)
1071
1103
 
1072
1104
  # Assemble
1105
+ self.minLayout = QHBoxLayout()
1106
+ self.minLayout.addWidget(QLabel(trAllWords, self))
1107
+ self.minLayout.addWidget(self.minWordCount)
1108
+ self.minLayout.addSpacing(mPx)
1109
+ self.minLayout.addWidget(QLabel(trAllChars, self))
1110
+ self.minLayout.addWidget(self.minCharCount)
1111
+ self.minLayout.addStretch(1)
1112
+ self.minLayout.setSpacing(mPx)
1113
+ self.minLayout.setContentsMargins(0, 0, 0, 0)
1114
+
1073
1115
  self.maxLayout = QHBoxLayout()
1074
1116
  self.maxLayout.addLayout(self.leftForm)
1075
1117
  self.maxLayout.addLayout(self.rightForm)
@@ -1077,6 +1119,7 @@ class _StatsWidget(QWidget):
1077
1119
  self.maxLayout.setSpacing(CONFIG.pxInt(32))
1078
1120
  self.maxLayout.setContentsMargins(0, 0, 0, 0)
1079
1121
 
1122
+ self.minWidget.setLayout(self.minLayout)
1080
1123
  self.maxWidget.setLayout(self.maxLayout)
1081
1124
 
1082
1125
  return