novelWriter 2.5b1__py3-none-any.whl → 2.5rc1__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-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/METADATA +1 -1
- {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/RECORD +61 -61
- {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +3 -3
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/project_pt_BR.json +74 -74
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/themes/cyberpunk_night.conf +1 -0
- novelwriter/assets/themes/default_dark.conf +1 -0
- novelwriter/assets/themes/default_light.conf +1 -0
- novelwriter/assets/themes/dracula.conf +1 -0
- novelwriter/assets/themes/solarized_dark.conf +1 -0
- novelwriter/assets/themes/solarized_light.conf +1 -0
- novelwriter/common.py +2 -3
- novelwriter/config.py +67 -15
- novelwriter/constants.py +8 -10
- novelwriter/core/buildsettings.py +5 -3
- novelwriter/core/coretools.py +3 -1
- novelwriter/core/docbuild.py +1 -0
- novelwriter/core/tohtml.py +69 -29
- novelwriter/core/tokenizer.py +83 -14
- novelwriter/core/toodt.py +48 -21
- novelwriter/core/toqdoc.py +25 -9
- novelwriter/dialogs/about.py +10 -15
- novelwriter/dialogs/docmerge.py +16 -16
- novelwriter/dialogs/docsplit.py +16 -16
- novelwriter/dialogs/editlabel.py +6 -8
- novelwriter/dialogs/preferences.py +94 -68
- novelwriter/dialogs/projectsettings.py +10 -10
- novelwriter/dialogs/quotes.py +9 -5
- novelwriter/dialogs/wordlist.py +6 -6
- novelwriter/enum.py +4 -5
- novelwriter/extensions/configlayout.py +23 -4
- novelwriter/extensions/modified.py +22 -3
- novelwriter/extensions/{circularprogress.py → progressbars.py} +26 -3
- novelwriter/extensions/statusled.py +28 -22
- novelwriter/gui/doceditor.py +20 -11
- novelwriter/gui/dochighlight.py +30 -39
- novelwriter/gui/docviewer.py +21 -14
- novelwriter/gui/mainmenu.py +11 -11
- novelwriter/gui/outline.py +3 -3
- novelwriter/gui/projtree.py +19 -28
- novelwriter/gui/search.py +10 -1
- novelwriter/gui/statusbar.py +25 -29
- novelwriter/gui/theme.py +3 -0
- novelwriter/guimain.py +91 -84
- novelwriter/shared.py +10 -8
- novelwriter/text/patterns.py +113 -0
- novelwriter/tools/dictionaries.py +2 -8
- novelwriter/tools/lipsum.py +8 -12
- novelwriter/tools/manusbuild.py +9 -9
- novelwriter/tools/manuscript.py +10 -5
- novelwriter/tools/manussettings.py +7 -3
- novelwriter/tools/noveldetails.py +10 -10
- novelwriter/tools/welcome.py +10 -10
- novelwriter/tools/writingstats.py +3 -3
- novelwriter/types.py +5 -2
- novelwriter/extensions/simpleprogress.py +0 -53
- {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/top_level.txt +0 -0
novelwriter/core/toqdoc.py
CHANGED
@@ -45,16 +45,18 @@ T_TextStyle = tuple[QTextBlockFormat, QTextCharFormat]
|
|
45
45
|
|
46
46
|
|
47
47
|
class TextDocumentTheme:
|
48
|
-
text:
|
48
|
+
text: QColor = QtBlack
|
49
49
|
highlight: QColor = QtTransparent
|
50
|
-
head:
|
51
|
-
comment:
|
52
|
-
note:
|
53
|
-
code:
|
54
|
-
modifier:
|
55
|
-
keyword:
|
56
|
-
tag:
|
57
|
-
optional:
|
50
|
+
head: QColor = QtBlack
|
51
|
+
comment: QColor = QtBlack
|
52
|
+
note: QColor = QtBlack
|
53
|
+
code: QColor = QtBlack
|
54
|
+
modifier: QColor = QtBlack
|
55
|
+
keyword: QColor = QtBlack
|
56
|
+
tag: QColor = QtBlack
|
57
|
+
optional: QColor = QtBlack
|
58
|
+
dialog: QColor = QtBlack
|
59
|
+
altdialog: QColor = QtBlack
|
58
60
|
|
59
61
|
|
60
62
|
def newBlock(cursor: QTextCursor, bFmt: QTextBlockFormat) -> None:
|
@@ -125,6 +127,7 @@ class ToQTextDocument(Tokenizer):
|
|
125
127
|
self._mSep = (mScale * self._marginSep[0], mScale * self._marginSep[1])
|
126
128
|
|
127
129
|
self._mIndent = mScale * 2.0
|
130
|
+
self._tIndent = mScale * self._firstWidth
|
128
131
|
|
129
132
|
# Block Format
|
130
133
|
# ============
|
@@ -133,6 +136,9 @@ class ToQTextDocument(Tokenizer):
|
|
133
136
|
self._blockFmt.setTopMargin(self._mText[0])
|
134
137
|
self._blockFmt.setBottomMargin(self._mText[1])
|
135
138
|
self._blockFmt.setAlignment(QtAlignJustify if self._doJustify else QtAlignAbsolute)
|
139
|
+
self._blockFmt.setLineHeight(
|
140
|
+
100*self._lineHeight, QTextBlockFormat.LineHeightTypes.ProportionalHeight
|
141
|
+
)
|
136
142
|
|
137
143
|
# Character Formats
|
138
144
|
# =================
|
@@ -224,6 +230,8 @@ class ToQTextDocument(Tokenizer):
|
|
224
230
|
bFmt.setLeftMargin(self._mIndent)
|
225
231
|
if tStyle & self.A_IND_R:
|
226
232
|
bFmt.setRightMargin(self._mIndent)
|
233
|
+
if tStyle & self.A_IND_T:
|
234
|
+
bFmt.setTextIndent(self._tIndent)
|
227
235
|
|
228
236
|
if tType == self.T_TEXT:
|
229
237
|
newBlock(cursor, bFmt)
|
@@ -337,6 +345,14 @@ class ToQTextDocument(Tokenizer):
|
|
337
345
|
cFmt.setVerticalAlignment(QtVAlignSub)
|
338
346
|
elif fmt == self.FMT_SUB_E:
|
339
347
|
cFmt.setVerticalAlignment(QtVAlignNormal)
|
348
|
+
elif fmt == self.FMT_DL_B:
|
349
|
+
cFmt.setForeground(self._theme.dialog)
|
350
|
+
elif fmt == self.FMT_DL_E:
|
351
|
+
cFmt.setForeground(self._theme.text)
|
352
|
+
elif fmt == self.FMT_ADL_B:
|
353
|
+
cFmt.setForeground(self._theme.altdialog)
|
354
|
+
elif fmt == self.FMT_ADL_E:
|
355
|
+
cFmt.setForeground(self._theme.text)
|
340
356
|
elif fmt == self.FMT_FNOTE:
|
341
357
|
xFmt = QTextCharFormat(self._cCode)
|
342
358
|
xFmt.setVerticalAlignment(QtVAlignSuper)
|
novelwriter/dialogs/about.py
CHANGED
@@ -33,14 +33,14 @@ from PyQt5.QtWidgets import (
|
|
33
33
|
from novelwriter import CONFIG, SHARED
|
34
34
|
from novelwriter.common import cssCol, readTextFile
|
35
35
|
from novelwriter.extensions.configlayout import NColourLabel
|
36
|
-
from novelwriter.extensions.modified import
|
36
|
+
from novelwriter.extensions.modified import NDialog
|
37
37
|
from novelwriter.extensions.versioninfo import VersionInfoWidget
|
38
38
|
from novelwriter.types import QtAlignRightTop, QtDialogClose
|
39
39
|
|
40
40
|
logger = logging.getLogger(__name__)
|
41
41
|
|
42
42
|
|
43
|
-
class GuiAbout(
|
43
|
+
class GuiAbout(NDialog):
|
44
44
|
|
45
45
|
def __init__(self, parent: QWidget) -> None:
|
46
46
|
super().__init__(parent=parent)
|
@@ -75,7 +75,7 @@ class GuiAbout(NNonBlockingDialog):
|
|
75
75
|
|
76
76
|
# Credits
|
77
77
|
self.lblCredits = NColourLabel(
|
78
|
-
self.tr("Credits"), scale=1.6,
|
78
|
+
self.tr("Credits"), self, scale=1.6, bold=True
|
79
79
|
)
|
80
80
|
|
81
81
|
self.txtCredits = QTextBrowser(self)
|
@@ -85,7 +85,7 @@ class GuiAbout(NNonBlockingDialog):
|
|
85
85
|
|
86
86
|
# Buttons
|
87
87
|
self.btnBox = QDialogButtonBox(QtDialogClose, self)
|
88
|
-
self.btnBox.rejected.connect(self.
|
88
|
+
self.btnBox.rejected.connect(self.reject)
|
89
89
|
|
90
90
|
# Assemble
|
91
91
|
self.innerBox = QVBoxLayout()
|
@@ -106,7 +106,9 @@ class GuiAbout(NNonBlockingDialog):
|
|
106
106
|
|
107
107
|
self.setLayout(self.outerBox)
|
108
108
|
self.setSizeGripEnabled(True)
|
109
|
+
|
109
110
|
self._setStyleSheet()
|
111
|
+
self._fillCreditsPage()
|
110
112
|
|
111
113
|
logger.debug("Ready: GuiAbout")
|
112
114
|
|
@@ -116,11 +118,6 @@ class GuiAbout(NNonBlockingDialog):
|
|
116
118
|
logger.debug("Delete: GuiAbout")
|
117
119
|
return
|
118
120
|
|
119
|
-
def populateGUI(self) -> None:
|
120
|
-
"""Populate tabs with text."""
|
121
|
-
self._fillCreditsPage()
|
122
|
-
return
|
123
|
-
|
124
121
|
##
|
125
122
|
# Events
|
126
123
|
##
|
@@ -128,7 +125,7 @@ class GuiAbout(NNonBlockingDialog):
|
|
128
125
|
def closeEvent(self, event: QCloseEvent) -> None:
|
129
126
|
"""Capture the close event and perform cleanup."""
|
130
127
|
event.accept()
|
131
|
-
self.
|
128
|
+
self.softDelete()
|
132
129
|
return
|
133
130
|
|
134
131
|
##
|
@@ -137,16 +134,14 @@ class GuiAbout(NNonBlockingDialog):
|
|
137
134
|
|
138
135
|
def _fillCreditsPage(self) -> None:
|
139
136
|
"""Load the content for the Credits page."""
|
140
|
-
|
141
|
-
|
142
|
-
if docText:
|
143
|
-
self.txtCredits.setHtml(docText)
|
137
|
+
if html := readTextFile(CONFIG.assetPath("text") / "credits_en.htm"):
|
138
|
+
self.txtCredits.setHtml(html)
|
144
139
|
else:
|
145
140
|
self.txtCredits.setHtml("Error loading credits text ...")
|
146
141
|
return
|
147
142
|
|
148
143
|
def _setStyleSheet(self) -> None:
|
149
|
-
"""Set stylesheet
|
144
|
+
"""Set stylesheet text document."""
|
150
145
|
baseCol = cssCol(self.palette().window().color())
|
151
146
|
self.txtCredits.setStyleSheet(
|
152
147
|
f"QTextBrowser {{border: none; background: {baseCol};}} "
|
novelwriter/dialogs/docmerge.py
CHANGED
@@ -27,21 +27,21 @@ from __future__ import annotations
|
|
27
27
|
import logging
|
28
28
|
|
29
29
|
from PyQt5.QtCore import Qt, pyqtSlot
|
30
|
-
from PyQt5.QtGui import QCloseEvent
|
31
30
|
from PyQt5.QtWidgets import (
|
32
|
-
QAbstractItemView,
|
33
|
-
|
31
|
+
QAbstractItemView, QDialogButtonBox, QGridLayout, QLabel, QListWidget,
|
32
|
+
QListWidgetItem, QVBoxLayout, QWidget
|
34
33
|
)
|
35
34
|
|
36
35
|
from novelwriter import CONFIG, SHARED
|
37
36
|
from novelwriter.extensions.configlayout import NColourLabel
|
37
|
+
from novelwriter.extensions.modified import NDialog
|
38
38
|
from novelwriter.extensions.switch import NSwitch
|
39
|
-
from novelwriter.types import QtDialogCancel, QtDialogOk, QtDialogReset, QtUserRole
|
39
|
+
from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtDialogReset, QtUserRole
|
40
40
|
|
41
41
|
logger = logging.getLogger(__name__)
|
42
42
|
|
43
43
|
|
44
|
-
class GuiDocMerge(
|
44
|
+
class GuiDocMerge(NDialog):
|
45
45
|
|
46
46
|
D_HANDLE = QtUserRole
|
47
47
|
|
@@ -58,7 +58,7 @@ class GuiDocMerge(QDialog):
|
|
58
58
|
self.headLabel.setFont(SHARED.theme.guiFontB)
|
59
59
|
self.helpLabel = NColourLabel(
|
60
60
|
self.tr("Drag and drop items to change the order, or uncheck to exclude."),
|
61
|
-
SHARED.theme.helpText,
|
61
|
+
self, color=SHARED.theme.helpText, wrap=True
|
62
62
|
)
|
63
63
|
|
64
64
|
iPx = SHARED.theme.baseIconHeight
|
@@ -117,7 +117,7 @@ class GuiDocMerge(QDialog):
|
|
117
117
|
logger.debug("Delete: GuiDocMerge")
|
118
118
|
return
|
119
119
|
|
120
|
-
def
|
120
|
+
def data(self) -> dict:
|
121
121
|
"""Return the user's choices."""
|
122
122
|
finalItems = []
|
123
123
|
for i in range(self.listBox.count()):
|
@@ -130,15 +130,15 @@ class GuiDocMerge(QDialog):
|
|
130
130
|
|
131
131
|
return self._data
|
132
132
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
return
|
133
|
+
@classmethod
|
134
|
+
def getData(cls, parent: QWidget, handle: str, items: list[str]) -> tuple[dict, bool]:
|
135
|
+
"""Pop the dialog and return the result."""
|
136
|
+
cls = GuiDocMerge(parent, handle, items)
|
137
|
+
cls.exec()
|
138
|
+
data = cls.data()
|
139
|
+
accepted = cls.result() == QtAccepted
|
140
|
+
cls.softDelete()
|
141
|
+
return data, accepted
|
142
142
|
|
143
143
|
##
|
144
144
|
# Private Slots
|
novelwriter/dialogs/docsplit.py
CHANGED
@@ -27,21 +27,21 @@ from __future__ import annotations
|
|
27
27
|
import logging
|
28
28
|
|
29
29
|
from PyQt5.QtCore import pyqtSlot
|
30
|
-
from PyQt5.QtGui import QCloseEvent
|
31
30
|
from PyQt5.QtWidgets import (
|
32
|
-
QAbstractItemView, QComboBox,
|
33
|
-
|
31
|
+
QAbstractItemView, QComboBox, QDialogButtonBox, QGridLayout, QLabel,
|
32
|
+
QListWidget, QListWidgetItem, QVBoxLayout, QWidget
|
34
33
|
)
|
35
34
|
|
36
35
|
from novelwriter import CONFIG, SHARED
|
37
36
|
from novelwriter.extensions.configlayout import NColourLabel
|
37
|
+
from novelwriter.extensions.modified import NDialog
|
38
38
|
from novelwriter.extensions.switch import NSwitch
|
39
|
-
from novelwriter.types import QtDialogCancel, QtDialogOk, QtUserRole
|
39
|
+
from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk, QtUserRole
|
40
40
|
|
41
41
|
logger = logging.getLogger(__name__)
|
42
42
|
|
43
43
|
|
44
|
-
class GuiDocSplit(
|
44
|
+
class GuiDocSplit(NDialog):
|
45
45
|
|
46
46
|
LINE_ROLE = QtUserRole
|
47
47
|
LEVEL_ROLE = QtUserRole + 1
|
@@ -62,7 +62,7 @@ class GuiDocSplit(QDialog):
|
|
62
62
|
self.headLabel.setFont(SHARED.theme.guiFontB)
|
63
63
|
self.helpLabel = NColourLabel(
|
64
64
|
self.tr("Select the maximum level to split into files."),
|
65
|
-
SHARED.theme.helpText,
|
65
|
+
self, color=SHARED.theme.helpText, wrap=True
|
66
66
|
)
|
67
67
|
|
68
68
|
# Values
|
@@ -145,7 +145,7 @@ class GuiDocSplit(QDialog):
|
|
145
145
|
logger.debug("Delete: GuiDocSplit")
|
146
146
|
return
|
147
147
|
|
148
|
-
def
|
148
|
+
def data(self) -> tuple[dict, list[str]]:
|
149
149
|
"""Return the user's choices. Also save the users options for
|
150
150
|
the next time the dialog is used.
|
151
151
|
"""
|
@@ -178,15 +178,15 @@ class GuiDocSplit(QDialog):
|
|
178
178
|
|
179
179
|
return self._data, self._text
|
180
180
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
return
|
181
|
+
@classmethod
|
182
|
+
def getData(cls, parent: QWidget, handle: str) -> tuple[dict, list[str], bool]:
|
183
|
+
"""Pop the dialog and return the result."""
|
184
|
+
cls = GuiDocSplit(parent, handle)
|
185
|
+
cls.exec()
|
186
|
+
data, text = cls.data()
|
187
|
+
accepted = cls.result() == QtAccepted
|
188
|
+
cls.softDelete()
|
189
|
+
return data, text, accepted
|
190
190
|
|
191
191
|
##
|
192
192
|
# Private Slots
|
novelwriter/dialogs/editlabel.py
CHANGED
@@ -25,18 +25,16 @@ from __future__ import annotations
|
|
25
25
|
|
26
26
|
import logging
|
27
27
|
|
28
|
-
from PyQt5.QtWidgets import
|
29
|
-
QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout,
|
30
|
-
QWidget
|
31
|
-
)
|
28
|
+
from PyQt5.QtWidgets import QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout, QWidget
|
32
29
|
|
33
30
|
from novelwriter import CONFIG
|
34
|
-
from novelwriter.
|
31
|
+
from novelwriter.extensions.modified import NDialog
|
32
|
+
from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk
|
35
33
|
|
36
34
|
logger = logging.getLogger(__name__)
|
37
35
|
|
38
36
|
|
39
|
-
class GuiEditLabel(
|
37
|
+
class GuiEditLabel(NDialog):
|
40
38
|
|
41
39
|
def __init__(self, parent: QWidget, text: str = "") -> None:
|
42
40
|
super().__init__(parent=parent)
|
@@ -91,6 +89,6 @@ class GuiEditLabel(QDialog):
|
|
91
89
|
cls = GuiEditLabel(parent, text=text)
|
92
90
|
cls.exec()
|
93
91
|
label = cls.itemLabel
|
94
|
-
accepted = cls.result() ==
|
95
|
-
cls.
|
92
|
+
accepted = cls.result() == QtAccepted
|
93
|
+
cls.softDelete()
|
96
94
|
return label, accepted
|
@@ -29,16 +29,18 @@ import logging
|
|
29
29
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
30
30
|
from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence
|
31
31
|
from PyQt5.QtWidgets import (
|
32
|
-
QAbstractButton,
|
33
|
-
|
32
|
+
QAbstractButton, QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout,
|
33
|
+
QLineEdit, QPushButton, QVBoxLayout, QWidget
|
34
34
|
)
|
35
35
|
|
36
36
|
from novelwriter import CONFIG, SHARED
|
37
37
|
from novelwriter.common import describeFont
|
38
|
-
from novelwriter.constants import
|
38
|
+
from novelwriter.constants import nwUnicode
|
39
39
|
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
40
40
|
from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
|
41
|
-
from novelwriter.extensions.modified import
|
41
|
+
from novelwriter.extensions.modified import (
|
42
|
+
NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox
|
43
|
+
)
|
42
44
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
43
45
|
from novelwriter.extensions.switch import NSwitch
|
44
46
|
from novelwriter.types import (
|
@@ -49,7 +51,7 @@ from novelwriter.types import (
|
|
49
51
|
logger = logging.getLogger(__name__)
|
50
52
|
|
51
53
|
|
52
|
-
class GuiPreferences(
|
54
|
+
class GuiPreferences(NDialog):
|
53
55
|
|
54
56
|
newPreferencesReady = pyqtSignal(bool, bool, bool, bool)
|
55
57
|
|
@@ -64,8 +66,8 @@ class GuiPreferences(QDialog):
|
|
64
66
|
|
65
67
|
# Title
|
66
68
|
self.titleLabel = NColourLabel(
|
67
|
-
self.tr("Preferences"), SHARED.theme.helpText,
|
68
|
-
|
69
|
+
self.tr("Preferences"), self, color=SHARED.theme.helpText,
|
70
|
+
scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
69
71
|
)
|
70
72
|
|
71
73
|
# Search Box
|
@@ -546,7 +548,7 @@ class GuiPreferences(QDialog):
|
|
546
548
|
self.allowOpenDial = NSwitch(self)
|
547
549
|
self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
|
548
550
|
self.mainForm.addRow(
|
549
|
-
self.tr("Allow open-ended
|
551
|
+
self.tr("Allow open-ended dialogue"), self.allowOpenDial,
|
550
552
|
self.tr("Highlight dialogue line with no closing quote.")
|
551
553
|
)
|
552
554
|
|
@@ -583,8 +585,8 @@ class GuiPreferences(QDialog):
|
|
583
585
|
self.altDialogClose.setText(CONFIG.altDialogClose)
|
584
586
|
|
585
587
|
self.mainForm.addRow(
|
586
|
-
self.tr("Alternative
|
587
|
-
self.tr("Custom highlighting of
|
588
|
+
self.tr("Alternative dialogue symbols"), [self.altDialogOpen, self.altDialogClose],
|
589
|
+
self.tr("Custom highlighting of dialogue text.")
|
588
590
|
)
|
589
591
|
|
590
592
|
self.highlightEmph = NSwitch(self)
|
@@ -693,64 +695,62 @@ class GuiPreferences(QDialog):
|
|
693
695
|
self.sidebar.addButton(title, section)
|
694
696
|
self.mainForm.addGroupLabel(title, section)
|
695
697
|
|
696
|
-
self.quoteSym = {}
|
697
|
-
|
698
698
|
# Single Quote Style
|
699
|
-
self.
|
700
|
-
self.
|
701
|
-
self.
|
702
|
-
self.
|
703
|
-
self.
|
704
|
-
self.
|
705
|
-
self.
|
706
|
-
self.
|
707
|
-
self.mainForm.addRow(
|
708
|
-
self.tr("Single quote open style"), self.
|
699
|
+
self.fmtSQuoteOpen = QLineEdit(self)
|
700
|
+
self.fmtSQuoteOpen.setMaxLength(1)
|
701
|
+
self.fmtSQuoteOpen.setReadOnly(True)
|
702
|
+
self.fmtSQuoteOpen.setFixedWidth(boxFixed)
|
703
|
+
self.fmtSQuoteOpen.setAlignment(QtAlignCenter)
|
704
|
+
self.fmtSQuoteOpen.setText(CONFIG.fmtSQuoteOpen)
|
705
|
+
self.btnSQuoteOpen = NIconToolButton(self, iSz, "quote")
|
706
|
+
self.btnSQuoteOpen.clicked.connect(self._changeSingleQuoteOpen)
|
707
|
+
self.mainForm.addRow(
|
708
|
+
self.tr("Single quote open style"), self.fmtSQuoteOpen,
|
709
709
|
self.tr("The symbol to use for a leading single quote."),
|
710
|
-
button=self.
|
710
|
+
button=self.btnSQuoteOpen
|
711
711
|
)
|
712
712
|
|
713
|
-
self.
|
714
|
-
self.
|
715
|
-
self.
|
716
|
-
self.
|
717
|
-
self.
|
718
|
-
self.
|
719
|
-
self.
|
720
|
-
self.
|
713
|
+
self.fmtSQuoteClose = QLineEdit(self)
|
714
|
+
self.fmtSQuoteClose.setMaxLength(1)
|
715
|
+
self.fmtSQuoteClose.setReadOnly(True)
|
716
|
+
self.fmtSQuoteClose.setFixedWidth(boxFixed)
|
717
|
+
self.fmtSQuoteClose.setAlignment(QtAlignCenter)
|
718
|
+
self.fmtSQuoteClose.setText(CONFIG.fmtSQuoteClose)
|
719
|
+
self.btnSQuoteClose = NIconToolButton(self, iSz, "quote")
|
720
|
+
self.btnSQuoteClose.clicked.connect(self._changeSingleQuoteClose)
|
721
721
|
self.mainForm.addRow(
|
722
|
-
self.tr("Single quote close style"), self.
|
722
|
+
self.tr("Single quote close style"), self.fmtSQuoteClose,
|
723
723
|
self.tr("The symbol to use for a trailing single quote."),
|
724
|
-
button=self.
|
724
|
+
button=self.btnSQuoteClose
|
725
725
|
)
|
726
726
|
|
727
727
|
# Double Quote Style
|
728
|
-
self.
|
729
|
-
self.
|
730
|
-
self.
|
731
|
-
self.
|
732
|
-
self.
|
733
|
-
self.
|
734
|
-
self.
|
735
|
-
self.
|
736
|
-
self.mainForm.addRow(
|
737
|
-
self.tr("Double quote open style"), self.
|
728
|
+
self.fmtDQuoteOpen = QLineEdit(self)
|
729
|
+
self.fmtDQuoteOpen.setMaxLength(1)
|
730
|
+
self.fmtDQuoteOpen.setReadOnly(True)
|
731
|
+
self.fmtDQuoteOpen.setFixedWidth(boxFixed)
|
732
|
+
self.fmtDQuoteOpen.setAlignment(QtAlignCenter)
|
733
|
+
self.fmtDQuoteOpen.setText(CONFIG.fmtDQuoteOpen)
|
734
|
+
self.btnDQuoteOpen = NIconToolButton(self, iSz, "quote")
|
735
|
+
self.btnDQuoteOpen.clicked.connect(self._changeDoubleQuoteOpen)
|
736
|
+
self.mainForm.addRow(
|
737
|
+
self.tr("Double quote open style"), self.fmtDQuoteOpen,
|
738
738
|
self.tr("The symbol to use for a leading double quote."),
|
739
|
-
button=self.
|
739
|
+
button=self.btnDQuoteOpen
|
740
740
|
)
|
741
741
|
|
742
|
-
self.
|
743
|
-
self.
|
744
|
-
self.
|
745
|
-
self.
|
746
|
-
self.
|
747
|
-
self.
|
748
|
-
self.
|
749
|
-
self.
|
742
|
+
self.fmtDQuoteClose = QLineEdit(self)
|
743
|
+
self.fmtDQuoteClose.setMaxLength(1)
|
744
|
+
self.fmtDQuoteClose.setReadOnly(True)
|
745
|
+
self.fmtDQuoteClose.setFixedWidth(boxFixed)
|
746
|
+
self.fmtDQuoteClose.setAlignment(QtAlignCenter)
|
747
|
+
self.fmtDQuoteClose.setText(CONFIG.fmtDQuoteClose)
|
748
|
+
self.btnDQuoteClose = NIconToolButton(self, iSz, "quote")
|
749
|
+
self.btnDQuoteClose.clicked.connect(self._changeDoubleQuoteClose)
|
750
750
|
self.mainForm.addRow(
|
751
|
-
self.tr("Double quote close style"), self.
|
751
|
+
self.tr("Double quote close style"), self.fmtDQuoteClose,
|
752
752
|
self.tr("The symbol to use for a trailing double quote."),
|
753
|
-
button=self.
|
753
|
+
button=self.btnDQuoteClose
|
754
754
|
)
|
755
755
|
|
756
756
|
self.mainForm.finalise()
|
@@ -767,13 +767,14 @@ class GuiPreferences(QDialog):
|
|
767
767
|
logger.debug("Close: GuiPreferences")
|
768
768
|
self._saveWindowSize()
|
769
769
|
event.accept()
|
770
|
-
|
771
|
-
self.done(nwConst.DLG_FINISHED)
|
772
|
-
self.deleteLater()
|
770
|
+
self.softDelete()
|
773
771
|
return
|
774
772
|
|
775
773
|
def keyPressEvent(self, event: QKeyEvent) -> None:
|
776
|
-
"""Overload keyPressEvent
|
774
|
+
"""Overload keyPressEvent and only accept escape. The main
|
775
|
+
purpose here is to prevent Enter/Return from closing the dialog
|
776
|
+
as it is used for the search box.
|
777
|
+
"""
|
777
778
|
if event.matches(QKeySequence.StandardKey.Cancel):
|
778
779
|
self.close()
|
779
780
|
event.ignore()
|
@@ -855,11 +856,36 @@ class GuiPreferences(QDialog):
|
|
855
856
|
self.fmtPadThin.setEnabled(state)
|
856
857
|
return
|
857
858
|
|
858
|
-
|
859
|
-
|
860
|
-
|
859
|
+
@pyqtSlot()
|
860
|
+
def _changeSingleQuoteOpen(self) -> None:
|
861
|
+
"""Change single quote open style."""
|
862
|
+
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteOpen.text())
|
863
|
+
if status:
|
864
|
+
self.fmtSQuoteOpen.setText(quote)
|
865
|
+
return
|
866
|
+
|
867
|
+
@pyqtSlot()
|
868
|
+
def _changeSingleQuoteClose(self) -> None:
|
869
|
+
"""Change single quote close style."""
|
870
|
+
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteClose.text())
|
871
|
+
if status:
|
872
|
+
self.fmtSQuoteClose.setText(quote)
|
873
|
+
return
|
874
|
+
|
875
|
+
@pyqtSlot()
|
876
|
+
def _changeDoubleQuoteOpen(self) -> None:
|
877
|
+
"""Change double quote open style."""
|
878
|
+
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteOpen.text())
|
879
|
+
if status:
|
880
|
+
self.fmtDQuoteOpen.setText(quote)
|
881
|
+
return
|
882
|
+
|
883
|
+
@pyqtSlot()
|
884
|
+
def _changeDoubleQuoteClose(self) -> None:
|
885
|
+
"""Change double quote close style."""
|
886
|
+
quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteClose.text())
|
861
887
|
if status:
|
862
|
-
self.
|
888
|
+
self.fmtDQuoteClose.setText(quote)
|
863
889
|
return
|
864
890
|
|
865
891
|
##
|
@@ -879,8 +905,8 @@ class GuiPreferences(QDialog):
|
|
879
905
|
refreshTree = False
|
880
906
|
|
881
907
|
# Appearance
|
882
|
-
guiLocale
|
883
|
-
guiTheme
|
908
|
+
guiLocale = self.guiLocale.currentData()
|
909
|
+
guiTheme = self.guiTheme.currentData()
|
884
910
|
|
885
911
|
updateTheme |= CONFIG.guiTheme != guiTheme
|
886
912
|
needsRestart |= CONFIG.guiLocale != guiLocale
|
@@ -977,10 +1003,10 @@ class GuiPreferences(QDialog):
|
|
977
1003
|
CONFIG.fmtPadThin = self.fmtPadThin.isChecked()
|
978
1004
|
|
979
1005
|
# Quotation Style
|
980
|
-
CONFIG.fmtSQuoteOpen = self.
|
981
|
-
CONFIG.fmtSQuoteClose = self.
|
982
|
-
CONFIG.fmtDQuoteOpen = self.
|
983
|
-
CONFIG.fmtDQuoteClose = self.
|
1006
|
+
CONFIG.fmtSQuoteOpen = self.fmtSQuoteOpen.text()
|
1007
|
+
CONFIG.fmtSQuoteClose = self.fmtSQuoteClose.text()
|
1008
|
+
CONFIG.fmtDQuoteOpen = self.fmtDQuoteOpen.text()
|
1009
|
+
CONFIG.fmtDQuoteClose = self.fmtDQuoteClose.text()
|
984
1010
|
|
985
1011
|
# Finalise
|
986
1012
|
CONFIG.saveConfig()
|
@@ -29,7 +29,7 @@ import logging
|
|
29
29
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
30
30
|
from PyQt5.QtGui import QCloseEvent, QColor
|
31
31
|
from PyQt5.QtWidgets import (
|
32
|
-
QAbstractItemView, QApplication, QColorDialog,
|
32
|
+
QAbstractItemView, QApplication, QColorDialog, QDialogButtonBox,
|
33
33
|
QHBoxLayout, QLineEdit, QMenu, QStackedWidget, QToolButton, QTreeWidget,
|
34
34
|
QTreeWidgetItem, QVBoxLayout, QWidget
|
35
35
|
)
|
@@ -40,7 +40,7 @@ from novelwriter.constants import nwLabels, trConst
|
|
40
40
|
from novelwriter.core.status import NWStatus, StatusEntry
|
41
41
|
from novelwriter.enum import nwStatusShape
|
42
42
|
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm
|
43
|
-
from novelwriter.extensions.modified import NComboBox, NIconToolButton
|
43
|
+
from novelwriter.extensions.modified import NComboBox, NDialog, NIconToolButton
|
44
44
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
45
45
|
from novelwriter.extensions.switch import NSwitch
|
46
46
|
from novelwriter.types import (
|
@@ -51,7 +51,7 @@ from novelwriter.types import (
|
|
51
51
|
logger = logging.getLogger(__name__)
|
52
52
|
|
53
53
|
|
54
|
-
class GuiProjectSettings(
|
54
|
+
class GuiProjectSettings(NDialog):
|
55
55
|
|
56
56
|
PAGE_SETTINGS = 0
|
57
57
|
PAGE_STATUS = 1
|
@@ -76,8 +76,8 @@ class GuiProjectSettings(QDialog):
|
|
76
76
|
|
77
77
|
# Title
|
78
78
|
self.titleLabel = NColourLabel(
|
79
|
-
self.tr("Project Settings"), SHARED.theme.helpText,
|
80
|
-
|
79
|
+
self.tr("Project Settings"), self, color=SHARED.theme.helpText,
|
80
|
+
scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
81
81
|
)
|
82
82
|
|
83
83
|
# SideBar
|
@@ -92,7 +92,7 @@ class GuiProjectSettings(QDialog):
|
|
92
92
|
# Buttons
|
93
93
|
self.buttonBox = QDialogButtonBox(QtDialogSave | QtDialogCancel, self)
|
94
94
|
self.buttonBox.accepted.connect(self._doSave)
|
95
|
-
self.buttonBox.rejected.connect(self.
|
95
|
+
self.buttonBox.rejected.connect(self.reject)
|
96
96
|
|
97
97
|
# Content
|
98
98
|
SHARED.project.countStatus()
|
@@ -147,7 +147,7 @@ class GuiProjectSettings(QDialog):
|
|
147
147
|
"""Capture the user closing the window and save settings."""
|
148
148
|
self._saveSettings()
|
149
149
|
event.accept()
|
150
|
-
self.
|
150
|
+
self.softDelete()
|
151
151
|
return
|
152
152
|
|
153
153
|
##
|
@@ -345,7 +345,7 @@ class _StatusPage(NFixedPage):
|
|
345
345
|
|
346
346
|
# Title
|
347
347
|
self.pageTitle = NColourLabel(
|
348
|
-
pageLabel, SHARED.theme.helpText,
|
348
|
+
pageLabel, self, color=SHARED.theme.helpText,
|
349
349
|
scale=NColourLabel.HEADER_SCALE
|
350
350
|
)
|
351
351
|
|
@@ -637,8 +637,8 @@ class _ReplacePage(NFixedPage):
|
|
637
637
|
|
638
638
|
# Title
|
639
639
|
self.pageTitle = NColourLabel(
|
640
|
-
self.tr("Text Auto-Replace for Preview and Build"),
|
641
|
-
SHARED.theme.helpText,
|
640
|
+
self.tr("Text Auto-Replace for Preview and Build"), self,
|
641
|
+
color=SHARED.theme.helpText, scale=NColourLabel.HEADER_SCALE
|
642
642
|
)
|
643
643
|
|
644
644
|
# List Box
|