novelWriter 2.7b1__py3-none-any.whl → 2.7rc1__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.
- novelwriter/__init__.py +17 -4
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/icons/remix_filled.icons +1 -0
- novelwriter/assets/icons/remix_outline.icons +1 -0
- novelwriter/assets/images/splash.png +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/manual_fr.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/snazzy.conf +3 -3
- novelwriter/assets/themes/snazzy.conf +48 -0
- novelwriter/common.py +10 -1
- novelwriter/config.py +96 -25
- novelwriter/constants.py +17 -0
- novelwriter/core/buildsettings.py +2 -0
- novelwriter/core/coretools.py +41 -34
- novelwriter/core/docbuild.py +1 -0
- novelwriter/core/index.py +25 -1
- novelwriter/core/indexdata.py +4 -1
- novelwriter/core/item.py +35 -24
- novelwriter/core/itemmodel.py +17 -13
- novelwriter/core/novelmodel.py +2 -0
- novelwriter/core/project.py +14 -14
- novelwriter/core/projectdata.py +42 -24
- novelwriter/core/projectxml.py +17 -7
- novelwriter/core/sessions.py +29 -13
- novelwriter/core/tree.py +9 -5
- novelwriter/dialogs/docmerge.py +2 -1
- novelwriter/dialogs/docsplit.py +6 -3
- novelwriter/dialogs/editlabel.py +11 -8
- novelwriter/dialogs/preferences.py +37 -26
- novelwriter/dialogs/projectsettings.py +3 -0
- novelwriter/extensions/configlayout.py +6 -2
- novelwriter/extensions/switch.py +16 -15
- novelwriter/extensions/switchbox.py +1 -0
- novelwriter/formats/tokenizer.py +2 -1
- novelwriter/gui/doceditor.py +98 -40
- novelwriter/gui/noveltree.py +11 -5
- novelwriter/gui/outline.py +9 -1
- novelwriter/gui/projtree.py +1 -0
- novelwriter/gui/search.py +1 -0
- novelwriter/gui/statusbar.py +14 -6
- novelwriter/gui/theme.py +25 -10
- novelwriter/guimain.py +29 -9
- novelwriter/splash.py +74 -0
- novelwriter/tools/lipsum.py +2 -1
- novelwriter/tools/manuscript.py +1 -1
- novelwriter/tools/manussettings.py +38 -13
- novelwriter/tools/noveldetails.py +9 -8
- novelwriter/tools/welcome.py +1 -0
- novelwriter/tools/writingstats.py +68 -45
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/METADATA +1 -1
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/RECORD +56 -53
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/WHEEL +1 -1
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/entry_points.txt +0 -0
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/licenses/LICENSE.md +0 -0
- {novelwriter-2.7b1.dist-info → novelwriter-2.7rc1.dist-info}/top_level.txt +0 -0
novelwriter/core/sessions.py
CHANGED
@@ -79,29 +79,36 @@ class NWSessionLog:
|
|
79
79
|
return False
|
80
80
|
|
81
81
|
now = time()
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
iWNovel, iWNotes, iCNovel, iCNotes = self._project.data.initCounts
|
83
|
+
cWNovel, cWNotes, cCNovel, cCNotes = self._project.data.currCounts
|
84
|
+
iWTotal = iWNovel + iWNotes
|
85
|
+
iCTotal = iCNovel + iCNotes
|
86
|
+
wDiff = cWNovel + cWNotes - iWTotal
|
87
|
+
cDiff = cCNovel + cCNotes - iCTotal
|
86
88
|
sTime = now - self._start
|
87
89
|
|
88
|
-
logger.info(
|
89
|
-
|
90
|
+
logger.info(
|
91
|
+
"The session lasted %d sec and added %d words abd %d characters",
|
92
|
+
int(sTime), wDiff, cDiff
|
93
|
+
)
|
94
|
+
if sTime < 300 and (wDiff == 0 or cDiff == 0):
|
90
95
|
logger.info("Session too short, skipping log entry")
|
91
96
|
return False
|
92
97
|
|
93
98
|
try:
|
94
99
|
if not sessFile.exists():
|
95
100
|
with open(sessFile, mode="w", encoding="utf-8") as fObj:
|
96
|
-
fObj.write(self.createInitial(
|
101
|
+
fObj.write(self.createInitial(iWTotal))
|
97
102
|
|
98
103
|
with open(sessFile, mode="a+", encoding="utf-8") as fObj:
|
99
104
|
fObj.write(self.createRecord(
|
100
105
|
start=formatTimeStamp(self._start),
|
101
106
|
end=formatTimeStamp(now),
|
102
|
-
novel=
|
103
|
-
notes=
|
104
|
-
idle=round(idleTime)
|
107
|
+
novel=cWNovel,
|
108
|
+
notes=cWNotes,
|
109
|
+
idle=round(idleTime),
|
110
|
+
cnovel=cCNovel,
|
111
|
+
cnotes=cCNotes,
|
105
112
|
))
|
106
113
|
|
107
114
|
except Exception:
|
@@ -129,10 +136,19 @@ class NWSessionLog:
|
|
129
136
|
data = json.dumps({"type": "initial", "offset": total})
|
130
137
|
return f"{data}\n"
|
131
138
|
|
132
|
-
def createRecord(
|
139
|
+
def createRecord(
|
140
|
+
self, start: str, end: str, novel: int, notes: int, idle: int,
|
141
|
+
cnovel: int = 0, cnotes: int = 0,
|
142
|
+
) -> str:
|
133
143
|
"""Low level function to create a log record."""
|
134
144
|
data = json.dumps({
|
135
|
-
"type": "record",
|
136
|
-
"
|
145
|
+
"type": "record",
|
146
|
+
"start": start,
|
147
|
+
"end": end,
|
148
|
+
"novel": novel,
|
149
|
+
"notes": notes,
|
150
|
+
"cnovel": cnovel,
|
151
|
+
"cnotes": cnotes,
|
152
|
+
"idle": idle,
|
137
153
|
})
|
138
154
|
return f"{data}\n"
|
novelwriter/core/tree.py
CHANGED
@@ -410,16 +410,20 @@ class NWTree:
|
|
410
410
|
|
411
411
|
return True
|
412
412
|
|
413
|
-
def
|
414
|
-
"""Loop over all entries and add up the word counts."""
|
415
|
-
noteWords = 0
|
413
|
+
def sumCounts(self) -> tuple[int, int, int, int]:
|
414
|
+
"""Loop over all entries and add up the word and char counts."""
|
416
415
|
novelWords = 0
|
416
|
+
notesWords = 0
|
417
|
+
novelChars = 0
|
418
|
+
notesChars = 0
|
417
419
|
for item in self._items.values():
|
418
420
|
if item.itemLayout == nwItemLayout.NOTE:
|
419
|
-
|
421
|
+
notesWords += item.wordCount
|
422
|
+
notesChars += item.charCount
|
420
423
|
elif item.itemLayout == nwItemLayout.DOCUMENT:
|
421
424
|
novelWords += item.wordCount
|
422
|
-
|
425
|
+
novelChars += item.charCount
|
426
|
+
return novelWords, notesWords, novelChars, notesChars
|
423
427
|
|
424
428
|
##
|
425
429
|
# Tree Item Methods
|
novelwriter/dialogs/docmerge.py
CHANGED
@@ -73,8 +73,9 @@ class GuiDocMerge(NDialog):
|
|
73
73
|
self.listBox.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
74
74
|
|
75
75
|
# Merge Options
|
76
|
-
self.trashLabel = QLabel(self.tr("Move merged items to Trash"), self)
|
77
76
|
self.trashSwitch = NSwitch(self, height=iPx)
|
77
|
+
self.trashLabel = QLabel(self.tr("Move merged items to Trash"), self)
|
78
|
+
self.trashLabel.setBuddy(self.trashSwitch)
|
78
79
|
|
79
80
|
self.optBox = QGridLayout()
|
80
81
|
self.optBox.addWidget(self.trashLabel, 0, 0)
|
novelwriter/dialogs/docsplit.py
CHANGED
@@ -90,16 +90,19 @@ class GuiDocSplit(NDialog):
|
|
90
90
|
self.splitLevel.currentIndexChanged.connect(self._reloadList)
|
91
91
|
|
92
92
|
# Split Options
|
93
|
-
self.folderLabel = QLabel(self.tr("Split into a new folder"), self)
|
94
93
|
self.folderSwitch = NSwitch(self, height=iPx)
|
95
94
|
self.folderSwitch.setChecked(intoFolder)
|
95
|
+
self.folderLabel = QLabel(self.tr("Split into a new folder"), self)
|
96
|
+
self.folderLabel.setBuddy(self.folderSwitch)
|
96
97
|
|
97
|
-
self.hierarchyLabel = QLabel(self.tr("Create document hierarchy"), self)
|
98
98
|
self.hierarchySwitch = NSwitch(self, height=iPx)
|
99
99
|
self.hierarchySwitch.setChecked(docHierarchy)
|
100
|
+
self.hierarchyLabel = QLabel(self.tr("Create document hierarchy"), self)
|
101
|
+
self.hierarchyLabel.setBuddy(self.hierarchySwitch)
|
100
102
|
|
101
|
-
self.trashLabel = QLabel(self.tr("Move split document to Trash"), self)
|
102
103
|
self.trashSwitch = NSwitch(self, height=iPx)
|
104
|
+
self.trashLabel = QLabel(self.tr("Move split document to Trash"), self)
|
105
|
+
self.trashLabel.setBuddy(self.trashSwitch)
|
103
106
|
|
104
107
|
self.optBox = QGridLayout()
|
105
108
|
self.optBox.addWidget(self.folderLabel, 0, 0)
|
novelwriter/dialogs/editlabel.py
CHANGED
@@ -43,11 +43,14 @@ class GuiEditLabel(NDialog):
|
|
43
43
|
self.setWindowTitle(self.tr("Item Label"))
|
44
44
|
|
45
45
|
# Item Label
|
46
|
-
self.
|
47
|
-
self.
|
48
|
-
self.
|
49
|
-
self.
|
50
|
-
self.
|
46
|
+
self.edtValue = QLineEdit(self)
|
47
|
+
self.edtValue.setMinimumWidth(220)
|
48
|
+
self.edtValue.setMaxLength(200)
|
49
|
+
self.edtValue.setText(text)
|
50
|
+
self.edtValue.selectAll()
|
51
|
+
|
52
|
+
self.lblValue = QLabel(self.tr("Label"), self)
|
53
|
+
self.lblValue.setBuddy(self.lblValue)
|
51
54
|
|
52
55
|
# Buttons
|
53
56
|
self.buttonBox = QDialogButtonBox(QtDialogOk | QtDialogCancel, self)
|
@@ -56,8 +59,8 @@ class GuiEditLabel(NDialog):
|
|
56
59
|
|
57
60
|
# Assemble
|
58
61
|
self.innerBox = QHBoxLayout()
|
59
|
-
self.innerBox.addWidget(
|
60
|
-
self.innerBox.addWidget(self.
|
62
|
+
self.innerBox.addWidget(self.lblValue, 0)
|
63
|
+
self.innerBox.addWidget(self.edtValue, 1)
|
61
64
|
self.innerBox.setSpacing(12)
|
62
65
|
|
63
66
|
self.outerBox = QVBoxLayout()
|
@@ -77,7 +80,7 @@ class GuiEditLabel(NDialog):
|
|
77
80
|
|
78
81
|
@property
|
79
82
|
def itemLabel(self) -> str:
|
80
|
-
return self.
|
83
|
+
return self.edtValue.text()
|
81
84
|
|
82
85
|
@classmethod
|
83
86
|
def getLabel(cls, parent: QWidget, text: str) -> tuple[str, bool]:
|
@@ -34,9 +34,9 @@ from PyQt6.QtWidgets import (
|
|
34
34
|
)
|
35
35
|
|
36
36
|
from novelwriter import CONFIG, SHARED
|
37
|
-
from novelwriter.common import compact, describeFont, uniqueCompact
|
37
|
+
from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact
|
38
38
|
from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL
|
39
|
-
from novelwriter.constants import nwLabels, nwUnicode, trConst
|
39
|
+
from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst
|
40
40
|
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
41
41
|
from novelwriter.extensions.configlayout import NColorLabel, NScrollableForm
|
42
42
|
from novelwriter.extensions.modified import (
|
@@ -80,6 +80,7 @@ class GuiPreferences(NDialog):
|
|
80
80
|
# SideBar
|
81
81
|
self.sidebar = NPagedSideBar(self)
|
82
82
|
self.sidebar.setLabelColor(SHARED.theme.helpText)
|
83
|
+
self.sidebar.setAccessibleName(self.titleLabel.text())
|
83
84
|
self.sidebar.buttonClicked.connect(self._sidebarClicked)
|
84
85
|
|
85
86
|
# Form
|
@@ -225,6 +226,14 @@ class GuiPreferences(NDialog):
|
|
225
226
|
self.tr("Turn off to use the Qt font dialog, which may have more options.")
|
226
227
|
)
|
227
228
|
|
229
|
+
# Use Character Count
|
230
|
+
self.useCharCount = NSwitch(self)
|
231
|
+
self.useCharCount.setChecked(CONFIG.useCharCount)
|
232
|
+
self.mainForm.addRow(
|
233
|
+
self.tr("Prefer character count over word count"), self.useCharCount,
|
234
|
+
self.tr("Display character count instead where available.")
|
235
|
+
)
|
236
|
+
|
228
237
|
# Document Style
|
229
238
|
# ==============
|
230
239
|
|
@@ -636,21 +645,20 @@ class GuiPreferences(NDialog):
|
|
636
645
|
self.tr("Lines starting with any of these symbols are dialogue.")
|
637
646
|
)
|
638
647
|
|
639
|
-
self.narratorBreak =
|
640
|
-
self.
|
641
|
-
|
642
|
-
|
643
|
-
|
648
|
+
self.narratorBreak = NComboBox(self)
|
649
|
+
self.narratorDialog = NComboBox(self)
|
650
|
+
for key, value in nwQuotes.DASHES.items():
|
651
|
+
label = trConst(value)
|
652
|
+
self.narratorBreak.addItem(label, key)
|
653
|
+
self.narratorDialog.addItem(label, key)
|
654
|
+
|
655
|
+
self.narratorBreak.setCurrentData(CONFIG.narratorBreak, "")
|
656
|
+
self.narratorDialog.setCurrentData(CONFIG.narratorDialog, "")
|
657
|
+
|
644
658
|
self.mainForm.addRow(
|
645
659
|
self.tr("Narrator break symbol"), self.narratorBreak,
|
646
660
|
self.tr("Symbol to indicate a narrator break in dialogue.")
|
647
661
|
)
|
648
|
-
|
649
|
-
self.narratorDialog = QLineEdit(self)
|
650
|
-
self.narratorDialog.setMaxLength(1)
|
651
|
-
self.narratorDialog.setFixedWidth(boxFixed)
|
652
|
-
self.narratorDialog.setAlignment(QtAlignCenter)
|
653
|
-
self.narratorDialog.setText(CONFIG.narratorDialog)
|
654
662
|
self.mainForm.addRow(
|
655
663
|
self.tr("Alternating dialogue/narration symbol"), self.narratorDialog,
|
656
664
|
self.tr("Alternates dialogue highlighting within any paragraph.")
|
@@ -957,21 +965,24 @@ class GuiPreferences(NDialog):
|
|
957
965
|
refreshTree = False
|
958
966
|
|
959
967
|
# Appearance
|
960
|
-
guiLocale
|
961
|
-
guiTheme
|
962
|
-
iconTheme
|
968
|
+
guiLocale = self.guiLocale.currentData()
|
969
|
+
guiTheme = self.guiTheme.currentData()
|
970
|
+
iconTheme = self.iconTheme.currentData()
|
971
|
+
useCharCount = self.useCharCount.isChecked()
|
963
972
|
|
964
973
|
updateTheme |= CONFIG.guiTheme != guiTheme
|
965
974
|
updateTheme |= CONFIG.iconTheme != iconTheme
|
966
975
|
needsRestart |= CONFIG.guiLocale != guiLocale
|
967
976
|
needsRestart |= CONFIG.guiFont != self._guiFont
|
968
|
-
|
969
|
-
|
970
|
-
CONFIG.
|
971
|
-
CONFIG.
|
972
|
-
CONFIG.
|
973
|
-
CONFIG.
|
974
|
-
CONFIG.
|
977
|
+
refreshTree |= CONFIG.useCharCount != useCharCount
|
978
|
+
|
979
|
+
CONFIG.guiLocale = guiLocale
|
980
|
+
CONFIG.guiTheme = guiTheme
|
981
|
+
CONFIG.iconTheme = iconTheme
|
982
|
+
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
983
|
+
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
984
|
+
CONFIG.nativeFont = self.nativeFont.isChecked()
|
985
|
+
CONFIG.useCharCount = useCharCount
|
975
986
|
CONFIG.setGuiFont(self._guiFont)
|
976
987
|
|
977
988
|
# Document Style
|
@@ -1034,9 +1045,9 @@ class GuiPreferences(NDialog):
|
|
1034
1045
|
# Text Highlighting
|
1035
1046
|
dialogueStyle = self.dialogStyle.currentData()
|
1036
1047
|
allowOpenDial = self.allowOpenDial.isChecked()
|
1037
|
-
dialogueLine =
|
1038
|
-
narratorBreak = self.narratorBreak.
|
1039
|
-
narratorDialog = self.narratorDialog.
|
1048
|
+
dialogueLine = processDialogSymbols(self.dialogLine.text())
|
1049
|
+
narratorBreak = self.narratorBreak.currentData()
|
1050
|
+
narratorDialog = self.narratorDialog.currentData()
|
1040
1051
|
altDialogOpen = compact(self.altDialogOpen.text())
|
1041
1052
|
altDialogClose = compact(self.altDialogClose.text())
|
1042
1053
|
highlightEmph = self.highlightEmph.isChecked()
|
@@ -86,6 +86,7 @@ class GuiProjectSettings(NDialog):
|
|
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("Settings"), self.PAGE_SETTINGS)
|
90
91
|
self.sidebar.addButton(self.tr("Status"), self.PAGE_STATUS)
|
91
92
|
self.sidebar.addButton(self.tr("Importance"), self.PAGE_IMPORT)
|
@@ -349,6 +350,7 @@ class _StatusPage(NFixedPage):
|
|
349
350
|
self.listBox.setHeaderLabels([self.tr("Label"), self.tr("Usage")])
|
350
351
|
self.listBox.setColumnWidth(self.C_LABEL, wCol0)
|
351
352
|
self.listBox.setIndentation(0)
|
353
|
+
self.listBox.setAccessibleName(pageLabel)
|
352
354
|
self.listBox.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
353
355
|
self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
354
356
|
self.listBox.itemSelectionChanged.connect(self._onSelectionChanged)
|
@@ -686,6 +688,7 @@ class _ReplacePage(NFixedPage):
|
|
686
688
|
self.listBox.setHeaderLabels([self.tr("Keyword"), self.tr("Replace With")])
|
687
689
|
self.listBox.setColumnWidth(self.C_KEY, wCol0)
|
688
690
|
self.listBox.setIndentation(0)
|
691
|
+
self.listBox.setAccessibleName(self.pageTitle.text())
|
689
692
|
self.listBox.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
690
693
|
self.listBox.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
691
694
|
self.listBox.itemSelectionChanged.connect(self._onSelectionChanged)
|
@@ -211,7 +211,8 @@ class NScrollableForm(QScrollArea):
|
|
211
211
|
else:
|
212
212
|
qWidget = widget
|
213
213
|
|
214
|
-
|
214
|
+
text = label or ""
|
215
|
+
qLabel = QLabel(text, self)
|
215
216
|
qLabel.setIndent(self._indent)
|
216
217
|
qLabel.setBuddy(qWidget)
|
217
218
|
|
@@ -227,6 +228,7 @@ class NScrollableForm(QScrollArea):
|
|
227
228
|
row.addLayout(labelBox, stretch[0])
|
228
229
|
if editable:
|
229
230
|
self._editable[editable] = qHelp
|
231
|
+
text = f"{text}: {helpText}"
|
230
232
|
else:
|
231
233
|
row.addWidget(qLabel, stretch[0])
|
232
234
|
|
@@ -235,6 +237,7 @@ class NScrollableForm(QScrollArea):
|
|
235
237
|
box.addWidget(qWidget, 1)
|
236
238
|
box.addWidget(QLabel(unit, self), 0)
|
237
239
|
row.addLayout(box, stretch[1])
|
240
|
+
text = f"{text} Unit: {unit}"
|
238
241
|
elif isinstance(button, QAbstractButton):
|
239
242
|
box = QHBoxLayout()
|
240
243
|
box.addWidget(qWidget, 1)
|
@@ -243,10 +246,11 @@ class NScrollableForm(QScrollArea):
|
|
243
246
|
else:
|
244
247
|
row.addWidget(qWidget, stretch[1])
|
245
248
|
|
249
|
+
self._first = False
|
246
250
|
self._layout.addLayout(row)
|
247
251
|
if label:
|
248
252
|
self._index[label.strip()] = qWidget
|
249
|
-
|
253
|
+
qLabel.setAccessibleName(text)
|
250
254
|
|
251
255
|
return
|
252
256
|
|
novelwriter/extensions/switch.py
CHANGED
@@ -23,12 +23,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
23
|
"""
|
24
24
|
from __future__ import annotations
|
25
25
|
|
26
|
-
from PyQt6.QtCore import QPropertyAnimation, Qt, pyqtProperty # pyright: ignore
|
27
|
-
from PyQt6.QtGui import QEnterEvent,
|
26
|
+
from PyQt6.QtCore import QPropertyAnimation, Qt, pyqtProperty, pyqtSlot # pyright: ignore
|
27
|
+
from PyQt6.QtGui import QEnterEvent, QPainter, QPaintEvent, QResizeEvent
|
28
28
|
from PyQt6.QtWidgets import QAbstractButton, QWidget
|
29
29
|
|
30
30
|
from novelwriter import SHARED
|
31
|
-
from novelwriter.types import
|
31
|
+
from novelwriter.types import QtNoPen, QtPaintAntiAlias, QtSizeFixed
|
32
32
|
|
33
33
|
|
34
34
|
class NSwitch(QAbstractButton):
|
@@ -50,6 +50,8 @@ class NSwitch(QAbstractButton):
|
|
50
50
|
self.setFixedHeight(self._xH)
|
51
51
|
self._offset = self._xR
|
52
52
|
|
53
|
+
self.clicked.connect(self._onClick)
|
54
|
+
|
53
55
|
return
|
54
56
|
|
55
57
|
##
|
@@ -94,7 +96,7 @@ class NSwitch(QAbstractButton):
|
|
94
96
|
painter.setRenderHint(QtPaintAntiAlias, True)
|
95
97
|
painter.setOpacity(1.0 if self.isEnabled() else 0.5)
|
96
98
|
|
97
|
-
painter.setPen(palette.mid().color())
|
99
|
+
painter.setPen(palette.highlight().color() if self.hasFocus() else palette.mid().color())
|
98
100
|
painter.setBrush(palette.highlight() if self.isChecked() else palette.alternateBase())
|
99
101
|
painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
|
100
102
|
|
@@ -106,19 +108,18 @@ class NSwitch(QAbstractButton):
|
|
106
108
|
|
107
109
|
return
|
108
110
|
|
109
|
-
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
|
110
|
-
"""Animate the switch on mouse release."""
|
111
|
-
super().mouseReleaseEvent(event)
|
112
|
-
if event.button() == QtMouseLeft:
|
113
|
-
anim = QPropertyAnimation(self, b"offset", self)
|
114
|
-
anim.setDuration(120)
|
115
|
-
anim.setStartValue(self._offset)
|
116
|
-
anim.setEndValue((self._xW - self._xR) if self.isChecked() else self._xR)
|
117
|
-
anim.start()
|
118
|
-
return
|
119
|
-
|
120
111
|
def enterEvent(self, event: QEnterEvent) -> None:
|
121
112
|
"""Change the cursor when hovering the button."""
|
122
113
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
123
114
|
super().enterEvent(event)
|
124
115
|
return
|
116
|
+
|
117
|
+
@pyqtSlot(bool)
|
118
|
+
def _onClick(self, checked: bool) -> None:
|
119
|
+
"""Animate the toggle action."""
|
120
|
+
anim = QPropertyAnimation(self, b"offset", self)
|
121
|
+
anim.setDuration(120)
|
122
|
+
anim.setStartValue(self._offset)
|
123
|
+
anim.setEndValue((self._xW - self._xR) if checked else self._xR)
|
124
|
+
anim.start()
|
125
|
+
return
|
@@ -100,6 +100,7 @@ class NSwitchBox(QScrollArea):
|
|
100
100
|
switch.toggled.connect(lambda state: self._emitSwitchSignal(identifier, state))
|
101
101
|
self._content.addWidget(switch, self._index, 2, QtAlignRight)
|
102
102
|
|
103
|
+
label.setBuddy(switch)
|
103
104
|
self._widgets.append(switch)
|
104
105
|
self._bumpIndex()
|
105
106
|
|
novelwriter/formats/tokenizer.py
CHANGED
@@ -614,7 +614,8 @@ class Tokenizer(ABC):
|
|
614
614
|
tStyle |= BlockFmt.JUSTIFY
|
615
615
|
|
616
616
|
if cStyle in (
|
617
|
-
nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN,
|
617
|
+
nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN,
|
618
|
+
nwComment.STORY, nwComment.NOTE,
|
618
619
|
):
|
619
620
|
bStyle = COMMENT_STYLE[cStyle]
|
620
621
|
tLine, tFmt = self._formatComment(bStyle, cKey, cText)
|