novelWriter 2.5.2__py3-none-any.whl → 2.6__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 (129) hide show
  1. {novelWriter-2.5.2.dist-info → novelWriter-2.6.dist-info}/METADATA +5 -4
  2. {novelWriter-2.5.2.dist-info → novelWriter-2.6.dist-info}/RECORD +126 -105
  3. {novelWriter-2.5.2.dist-info → novelWriter-2.6.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 +4 -2
  18. novelwriter/assets/i18n/project_en_GB.json +1 -0
  19. novelwriter/assets/i18n/project_en_US.json +2 -0
  20. novelwriter/assets/i18n/project_it_IT.json +2 -0
  21. novelwriter/assets/i18n/project_ja_JP.json +2 -0
  22. novelwriter/assets/i18n/project_nb_NO.json +2 -0
  23. novelwriter/assets/i18n/project_nl_NL.json +2 -0
  24. novelwriter/assets/i18n/project_pl_PL.json +2 -0
  25. novelwriter/assets/i18n/project_pt_BR.json +2 -0
  26. novelwriter/assets/i18n/project_ru_RU.json +11 -0
  27. novelwriter/assets/i18n/project_zh_CN.json +2 -0
  28. novelwriter/assets/icons/typicons_dark/icons.conf +8 -0
  29. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
  30. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
  31. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
  32. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
  33. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
  34. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
  35. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
  36. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
  37. novelwriter/assets/icons/typicons_light/icons.conf +8 -0
  38. novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
  39. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
  40. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
  41. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
  42. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
  43. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
  44. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
  45. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
  46. novelwriter/assets/manual.pdf +0 -0
  47. novelwriter/assets/sample.zip +0 -0
  48. novelwriter/assets/text/credits_en.htm +1 -0
  49. novelwriter/assets/themes/default_light.conf +2 -2
  50. novelwriter/common.py +101 -3
  51. novelwriter/config.py +30 -17
  52. novelwriter/constants.py +189 -81
  53. novelwriter/core/buildsettings.py +74 -40
  54. novelwriter/core/coretools.py +146 -148
  55. novelwriter/core/docbuild.py +133 -171
  56. novelwriter/core/document.py +1 -1
  57. novelwriter/core/index.py +39 -38
  58. novelwriter/core/item.py +42 -9
  59. novelwriter/core/itemmodel.py +518 -0
  60. novelwriter/core/options.py +5 -2
  61. novelwriter/core/project.py +68 -90
  62. novelwriter/core/projectdata.py +8 -2
  63. novelwriter/core/projectxml.py +1 -1
  64. novelwriter/core/sessions.py +1 -1
  65. novelwriter/core/spellcheck.py +10 -15
  66. novelwriter/core/status.py +24 -8
  67. novelwriter/core/storage.py +1 -1
  68. novelwriter/core/tree.py +269 -288
  69. novelwriter/dialogs/about.py +1 -1
  70. novelwriter/dialogs/docmerge.py +8 -18
  71. novelwriter/dialogs/docsplit.py +1 -1
  72. novelwriter/dialogs/editlabel.py +1 -1
  73. novelwriter/dialogs/preferences.py +47 -34
  74. novelwriter/dialogs/projectsettings.py +149 -99
  75. novelwriter/dialogs/quotes.py +1 -1
  76. novelwriter/dialogs/wordlist.py +11 -10
  77. novelwriter/enum.py +37 -24
  78. novelwriter/error.py +2 -2
  79. novelwriter/extensions/configlayout.py +28 -13
  80. novelwriter/extensions/eventfilters.py +1 -1
  81. novelwriter/extensions/modified.py +30 -6
  82. novelwriter/extensions/novelselector.py +4 -3
  83. novelwriter/extensions/pagedsidebar.py +9 -9
  84. novelwriter/extensions/progressbars.py +4 -4
  85. novelwriter/extensions/statusled.py +3 -3
  86. novelwriter/extensions/switch.py +3 -3
  87. novelwriter/extensions/switchbox.py +1 -1
  88. novelwriter/extensions/versioninfo.py +1 -1
  89. novelwriter/formats/shared.py +156 -0
  90. novelwriter/formats/todocx.py +1191 -0
  91. novelwriter/formats/tohtml.py +454 -0
  92. novelwriter/{core → formats}/tokenizer.py +497 -495
  93. novelwriter/formats/tomarkdown.py +218 -0
  94. novelwriter/{core → formats}/toodt.py +312 -433
  95. novelwriter/formats/toqdoc.py +486 -0
  96. novelwriter/formats/toraw.py +91 -0
  97. novelwriter/gui/doceditor.py +347 -287
  98. novelwriter/gui/dochighlight.py +97 -85
  99. novelwriter/gui/docviewer.py +90 -33
  100. novelwriter/gui/docviewerpanel.py +18 -26
  101. novelwriter/gui/editordocument.py +18 -3
  102. novelwriter/gui/itemdetails.py +27 -29
  103. novelwriter/gui/mainmenu.py +130 -64
  104. novelwriter/gui/noveltree.py +46 -48
  105. novelwriter/gui/outline.py +202 -256
  106. novelwriter/gui/projtree.py +590 -1238
  107. novelwriter/gui/search.py +11 -19
  108. novelwriter/gui/sidebar.py +8 -7
  109. novelwriter/gui/statusbar.py +20 -3
  110. novelwriter/gui/theme.py +11 -6
  111. novelwriter/guimain.py +101 -201
  112. novelwriter/shared.py +67 -28
  113. novelwriter/text/counting.py +3 -1
  114. novelwriter/text/patterns.py +169 -61
  115. novelwriter/tools/dictionaries.py +3 -3
  116. novelwriter/tools/lipsum.py +1 -1
  117. novelwriter/tools/manusbuild.py +15 -13
  118. novelwriter/tools/manuscript.py +121 -79
  119. novelwriter/tools/manussettings.py +424 -291
  120. novelwriter/tools/noveldetails.py +1 -1
  121. novelwriter/tools/welcome.py +6 -6
  122. novelwriter/tools/writingstats.py +4 -4
  123. novelwriter/types.py +25 -9
  124. novelwriter/core/tohtml.py +0 -530
  125. novelwriter/core/tomarkdown.py +0 -252
  126. novelwriter/core/toqdoc.py +0 -419
  127. {novelWriter-2.5.2.dist-info → novelWriter-2.6.dist-info}/LICENSE.md +0 -0
  128. {novelWriter-2.5.2.dist-info → novelWriter-2.6.dist-info}/entry_points.txt +0 -0
  129. {novelWriter-2.5.2.dist-info → novelWriter-2.6.dist-info}/top_level.txt +0 -0
novelwriter/gui/search.py CHANGED
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-03-21 [2.4b1] GuiProjectSearch
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
@@ -30,15 +30,18 @@ from time import time
30
30
  from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
31
31
  from PyQt5.QtGui import QCursor, QKeyEvent
32
32
  from PyQt5.QtWidgets import (
33
- QApplication, QFrame, QHBoxLayout, QHeaderView, QLabel, QLineEdit,
34
- QToolBar, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
33
+ QApplication, QFrame, QHBoxLayout, QLabel, QLineEdit, QToolBar,
34
+ QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
35
35
  )
36
36
 
37
37
  from novelwriter import CONFIG, SHARED
38
38
  from novelwriter.common import checkInt, cssCol
39
39
  from novelwriter.core.coretools import DocSearch
40
40
  from novelwriter.core.item import NWItem
41
- from novelwriter.types import QtAlignMiddle, QtAlignRight, QtUserRole
41
+ from novelwriter.types import (
42
+ QtAlignMiddle, QtAlignRight, QtHeaderStretch, QtHeaderToContents,
43
+ QtUserRole
44
+ )
42
45
 
43
46
  logger = logging.getLogger(__name__)
44
47
 
@@ -120,8 +123,8 @@ class GuiProjectSearch(QWidget):
120
123
 
121
124
  treeHeader = self.searchResult.header()
122
125
  treeHeader.setStretchLastSection(False)
123
- treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.Stretch)
124
- treeHeader.setSectionResizeMode(self.C_COUNT, QHeaderView.ResizeMode.ResizeToContents)
126
+ treeHeader.setSectionResizeMode(self.C_NAME, QtHeaderStretch)
127
+ treeHeader.setSectionResizeMode(self.C_COUNT, QtHeaderToContents)
125
128
 
126
129
  # Assemble
127
130
  self.headerBox = QHBoxLayout()
@@ -130,12 +133,8 @@ class GuiProjectSearch(QWidget):
130
133
  self.headerBox.setContentsMargins(0, 0, 0, 0)
131
134
  self.headerBox.setSpacing(0)
132
135
 
133
- self.headerWidget = QWidget(self)
134
- self.headerWidget.setLayout(self.headerBox)
135
- self.headerWidget.setContentsMargins(0, 0, 0, 0)
136
-
137
136
  self.outerBox = QVBoxLayout()
138
- self.outerBox.addWidget(self.headerWidget, 0)
137
+ self.outerBox.addLayout(self.headerBox, 0)
139
138
  self.outerBox.addWidget(self.searchText, 0)
140
139
  self.outerBox.addWidget(self.searchResult, 1)
141
140
  self.outerBox.setContentsMargins(0, 0, 0, 0)
@@ -161,9 +160,6 @@ class GuiProjectSearch(QWidget):
161
160
  colBase = cssCol(qPalette.base().color())
162
161
  colFocus = cssCol(qPalette.highlight().color())
163
162
 
164
- self.headerWidget.setStyleSheet(f"QWidget {{background: {colBase};}}")
165
- self.headerWidget.setAutoFillBackground(True)
166
-
167
163
  self.setStyleSheet(
168
164
  "QToolBar {padding: 0; background: none;} "
169
165
  f"QLineEdit {{border: {bPx}px solid {colBase}; padding: {mPx}px;}} "
@@ -331,15 +327,11 @@ class GuiProjectSearch(QWidget):
331
327
  """Populate the result tree."""
332
328
  if results and nwItem:
333
329
  tHandle = nwItem.itemHandle
334
- docIcon = SHARED.theme.getItemIcon(
335
- nwItem.itemType, nwItem.itemClass,
336
- nwItem.itemLayout, nwItem.mainHeading
337
- )
338
330
  ext = "+" if capped else ""
339
331
 
340
332
  tItem = QTreeWidgetItem()
341
333
  tItem.setText(self.C_NAME, nwItem.itemName)
342
- tItem.setIcon(self.C_NAME, docIcon)
334
+ tItem.setIcon(self.C_NAME, nwItem.getMainIcon())
343
335
  tItem.setData(self.C_NAME, self.D_HANDLE, tHandle)
344
336
  tItem.setText(self.C_COUNT, f"({len(results):n}{ext})")
345
337
  tItem.setTextAlignment(self.C_COUNT, QtAlignRight)
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2022-05-10 [2.0rc1] GuiSideBar
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2022 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
@@ -32,6 +32,7 @@ from PyQt5.QtGui import QPalette
32
32
  from PyQt5.QtWidgets import QMenu, QVBoxLayout, QWidget
33
33
 
34
34
  from novelwriter import CONFIG, SHARED
35
+ from novelwriter.common import qtLambda
35
36
  from novelwriter.enum import nwView
36
37
  from novelwriter.extensions.eventfilters import StatusTipFilter
37
38
  from novelwriter.extensions.modified import NIconToolButton
@@ -54,7 +55,7 @@ class GuiSideBar(QWidget):
54
55
 
55
56
  self.mainGui = mainGui
56
57
 
57
- iPx = int(1.2*SHARED.theme.baseButtonHeight)
58
+ iPx = int(1.25*SHARED.theme.baseButtonHeight)
58
59
  iSz = QSize(iPx, iPx)
59
60
 
60
61
  self.setContentsMargins(0, 0, 0, 0)
@@ -63,19 +64,19 @@ class GuiSideBar(QWidget):
63
64
  # Buttons
64
65
  self.tbProject = NIconToolButton(self, iSz)
65
66
  self.tbProject.setToolTip("{0} [Ctrl+T]".format(self.tr("Project Tree View")))
66
- self.tbProject.clicked.connect(lambda: self.requestViewChange.emit(nwView.PROJECT))
67
+ self.tbProject.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.PROJECT))
67
68
 
68
69
  self.tbNovel = NIconToolButton(self, iSz)
69
70
  self.tbNovel.setToolTip("{0} [Ctrl+T]".format(self.tr("Novel Tree View")))
70
- self.tbNovel.clicked.connect(lambda: self.requestViewChange.emit(nwView.NOVEL))
71
+ self.tbNovel.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.NOVEL))
71
72
 
72
73
  self.tbSearch = NIconToolButton(self, iSz)
73
74
  self.tbSearch.setToolTip("{0} [Ctrl+Shift+F]".format(self.tr("Project Search")))
74
- self.tbSearch.clicked.connect(lambda: self.requestViewChange.emit(nwView.SEARCH))
75
+ self.tbSearch.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.SEARCH))
75
76
 
76
77
  self.tbOutline = NIconToolButton(self, iSz)
77
78
  self.tbOutline.setToolTip("{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
78
- self.tbOutline.clicked.connect(lambda: self.requestViewChange.emit(nwView.OUTLINE))
79
+ self.tbOutline.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.OUTLINE))
79
80
 
80
81
  self.tbBuild = NIconToolButton(self, iSz)
81
82
  self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
@@ -113,7 +114,7 @@ class GuiSideBar(QWidget):
113
114
  self.outerBox.addWidget(self.tbStats)
114
115
  self.outerBox.addWidget(self.tbSettings)
115
116
  self.outerBox.setContentsMargins(0, 0, 0, 0)
116
- self.outerBox.setSpacing(CONFIG.pxInt(4))
117
+ self.outerBox.setSpacing(CONFIG.pxInt(6))
117
118
 
118
119
  self.setLayout(self.outerBox)
119
120
  self.updateTheme()
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2019-04-20 [0.0.1] GuiMainStatus
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
@@ -35,6 +35,7 @@ from novelwriter import CONFIG, SHARED
35
35
  from novelwriter.common import formatTime
36
36
  from novelwriter.constants import nwConst
37
37
  from novelwriter.enum import nwTrinary
38
+ from novelwriter.extensions.modified import NClickableLabel
38
39
  from novelwriter.extensions.statusled import StatusLED
39
40
 
40
41
  logger = logging.getLogger(__name__)
@@ -92,12 +93,16 @@ class GuiMainStatus(QStatusBar):
92
93
 
93
94
  # The Session Clock
94
95
  # Set the minimum width so the label doesn't rescale every second
95
- self.timeIcon = QLabel(self)
96
- self.timeText = QLabel("", self)
96
+ self.timeIcon = NClickableLabel(self)
97
+ self.timeIcon.mouseClicked.connect(self._onClickTimerLabel)
98
+
99
+ self.timeText = NClickableLabel("", self)
97
100
  self.timeText.setToolTip(self.tr("Session Time"))
98
101
  self.timeText.setMinimumWidth(SHARED.theme.getTextWidth("00:00:00:"))
99
102
  self.timeIcon.setContentsMargins(0, 0, 0, 0)
100
103
  self.timeText.setContentsMargins(0, 0, 0, 0)
104
+ self.timeText.setVisible(CONFIG.showSessionTime)
105
+ self.timeText.mouseClicked.connect(self._onClickTimerLabel)
101
106
  self.addPermanentWidget(self.timeIcon)
102
107
  self.addPermanentWidget(self.timeText)
103
108
 
@@ -224,6 +229,18 @@ class GuiMainStatus(QStatusBar):
224
229
  self.setDocumentStatus(nwTrinary.NEGATIVE if status else nwTrinary.POSITIVE)
225
230
  return
226
231
 
232
+ ##
233
+ # Private Slots
234
+ ##
235
+
236
+ @pyqtSlot()
237
+ def _onClickTimerLabel(self) -> None:
238
+ """Process mouse click on timer label."""
239
+ state = not CONFIG.showSessionTime
240
+ self.timeText.setVisible(state)
241
+ CONFIG.showSessionTime = state
242
+ return
243
+
227
244
  ##
228
245
  # Debug
229
246
  ##
novelwriter/gui/theme.py CHANGED
@@ -7,7 +7,7 @@ Created: 2019-05-18 [0.1.3] GuiTheme
7
7
  Created: 2019-11-08 [0.4] GuiIcons
8
8
 
9
9
  This file is a part of novelWriter
10
- Copyright 2018–2024, Veronica Berglyd Olsen
10
+ Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
11
11
 
12
12
  This program is free software: you can redistribute it and/or modify
13
13
  it under the terms of the GNU General Public License as published by
@@ -151,6 +151,9 @@ class GuiTheme:
151
151
  self.guiFont = QApplication.font()
152
152
  self.guiFontB = QApplication.font()
153
153
  self.guiFontB.setBold(True)
154
+ self.guiFontBU = QApplication.font()
155
+ self.guiFontBU.setBold(True)
156
+ self.guiFontBU.setUnderline(True)
154
157
  self.guiFontSmall = QApplication.font()
155
158
  self.guiFontSmall.setPointSizeF(0.9*self.guiFont.pointSizeF())
156
159
 
@@ -500,13 +503,15 @@ class GuiIcons:
500
503
 
501
504
  # Format Icons
502
505
  "fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_mark", "fmt_strike",
503
- "fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline",
506
+ "fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline", "margin_bottom",
507
+ "margin_left", "margin_right", "margin_top", "size_height", "size_width",
504
508
 
505
509
  # General Button Icons
506
- "add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross",
507
- "document", "down", "edit", "export", "font", "forward", "import", "list", "maximise",
508
- "menu", "minimise", "more", "noncheckable", "open", "panel", "quote", "refresh", "remove",
509
- "revert", "search_replace", "search", "settings", "star", "unchecked", "up", "view",
510
+ "add", "add_document", "backward", "bookmark", "browse", "checked", "close", "copy",
511
+ "cross", "document", "down", "edit", "export", "font", "forward", "import", "list",
512
+ "maximise", "menu", "minimise", "more", "noncheckable", "open", "panel", "quote",
513
+ "refresh", "remove", "revert", "search_replace", "search", "settings", "star", "toolbar",
514
+ "unchecked", "up", "view",
510
515
 
511
516
  # Switches
512
517
  "sticky-on", "sticky-off",