novelWriter 2.4.2__py3-none-any.whl → 2.5b1__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.4.2.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/RECORD +109 -101
- novelwriter/__init__.py +33 -39
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
- novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +2 -0
- novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
- novelwriter/assets/syntax/default_dark.conf +32 -18
- novelwriter/assets/syntax/default_light.conf +24 -10
- novelwriter/assets/syntax/dracula.conf +44 -0
- novelwriter/assets/syntax/grey_dark.conf +5 -4
- novelwriter/assets/syntax/grey_light.conf +5 -4
- novelwriter/assets/syntax/light_owl.conf +7 -6
- novelwriter/assets/syntax/night_owl.conf +7 -6
- novelwriter/assets/syntax/snazzy.conf +42 -0
- novelwriter/assets/syntax/solarized_dark.conf +4 -3
- novelwriter/assets/syntax/solarized_light.conf +4 -3
- novelwriter/assets/syntax/tango.conf +27 -11
- novelwriter/assets/syntax/tomorrow.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night.conf +7 -6
- novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
- novelwriter/assets/text/credits_en.htm +4 -1
- novelwriter/assets/themes/cyberpunk_night.conf +2 -0
- novelwriter/assets/themes/default_dark.conf +1 -0
- novelwriter/assets/themes/default_light.conf +1 -0
- novelwriter/assets/themes/dracula.conf +47 -0
- novelwriter/assets/themes/solarized_dark.conf +1 -0
- novelwriter/assets/themes/solarized_light.conf +1 -0
- novelwriter/common.py +31 -9
- novelwriter/config.py +118 -84
- novelwriter/constants.py +40 -26
- novelwriter/core/buildsettings.py +63 -66
- novelwriter/core/coretools.py +2 -22
- novelwriter/core/docbuild.py +51 -40
- novelwriter/core/document.py +3 -5
- novelwriter/core/index.py +115 -45
- novelwriter/core/item.py +8 -19
- novelwriter/core/options.py +2 -4
- novelwriter/core/project.py +23 -57
- novelwriter/core/projectdata.py +1 -3
- novelwriter/core/projectxml.py +12 -15
- novelwriter/core/sessions.py +3 -5
- novelwriter/core/spellcheck.py +4 -9
- novelwriter/core/status.py +211 -164
- novelwriter/core/storage.py +0 -8
- novelwriter/core/tohtml.py +94 -100
- novelwriter/core/tokenizer.py +199 -112
- novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
- novelwriter/core/toodt.py +212 -148
- novelwriter/core/toqdoc.py +403 -0
- novelwriter/core/tree.py +5 -7
- novelwriter/dialogs/about.py +3 -5
- novelwriter/dialogs/docmerge.py +1 -3
- novelwriter/dialogs/docsplit.py +1 -3
- novelwriter/dialogs/editlabel.py +0 -2
- novelwriter/dialogs/preferences.py +111 -88
- novelwriter/dialogs/projectsettings.py +216 -180
- novelwriter/dialogs/quotes.py +3 -4
- novelwriter/dialogs/wordlist.py +3 -9
- novelwriter/enum.py +31 -25
- novelwriter/error.py +8 -15
- novelwriter/extensions/circularprogress.py +5 -6
- novelwriter/extensions/configlayout.py +18 -18
- novelwriter/extensions/eventfilters.py +1 -5
- novelwriter/extensions/modified.py +50 -13
- novelwriter/extensions/novelselector.py +1 -3
- novelwriter/extensions/pagedsidebar.py +9 -12
- novelwriter/extensions/simpleprogress.py +1 -3
- novelwriter/extensions/statusled.py +1 -3
- novelwriter/extensions/switch.py +4 -6
- novelwriter/extensions/switchbox.py +7 -6
- novelwriter/extensions/versioninfo.py +3 -9
- novelwriter/gui/doceditor.py +132 -133
- novelwriter/gui/dochighlight.py +237 -183
- novelwriter/gui/docviewer.py +61 -97
- novelwriter/gui/docviewerpanel.py +3 -10
- novelwriter/gui/editordocument.py +1 -3
- novelwriter/gui/itemdetails.py +7 -11
- novelwriter/gui/mainmenu.py +11 -7
- novelwriter/gui/noveltree.py +11 -24
- novelwriter/gui/outline.py +11 -23
- novelwriter/gui/projtree.py +26 -43
- novelwriter/gui/search.py +1 -3
- novelwriter/gui/sidebar.py +2 -6
- novelwriter/gui/statusbar.py +6 -10
- novelwriter/gui/theme.py +26 -51
- novelwriter/guimain.py +50 -71
- novelwriter/shared.py +30 -15
- novelwriter/tools/dictionaries.py +12 -15
- novelwriter/tools/lipsum.py +2 -4
- novelwriter/tools/manusbuild.py +1 -3
- novelwriter/tools/manuscript.py +71 -144
- novelwriter/tools/manussettings.py +67 -73
- novelwriter/tools/noveldetails.py +6 -11
- novelwriter/tools/welcome.py +2 -16
- novelwriter/tools/writingstats.py +6 -9
- novelwriter/types.py +45 -3
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/top_level.txt +0 -0
novelwriter/dialogs/wordlist.py
CHANGED
@@ -25,14 +25,13 @@ from __future__ import annotations
|
|
25
25
|
|
26
26
|
import logging
|
27
27
|
|
28
|
-
from typing import TYPE_CHECKING
|
29
28
|
from pathlib import Path
|
30
29
|
|
31
30
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
32
31
|
from PyQt5.QtGui import QCloseEvent
|
33
32
|
from PyQt5.QtWidgets import (
|
34
33
|
QAbstractItemView, QApplication, QDialog, QDialogButtonBox, QFileDialog,
|
35
|
-
QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout
|
34
|
+
QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout, QWidget
|
36
35
|
)
|
37
36
|
|
38
37
|
from novelwriter import CONFIG, SHARED
|
@@ -42,9 +41,6 @@ from novelwriter.extensions.configlayout import NColourLabel
|
|
42
41
|
from novelwriter.extensions.modified import NIconToolButton
|
43
42
|
from novelwriter.types import QtDialogClose, QtDialogSave
|
44
43
|
|
45
|
-
if TYPE_CHECKING: # pragma: no cover
|
46
|
-
from novelwriter.guimain import GuiMain
|
47
|
-
|
48
44
|
logger = logging.getLogger(__name__)
|
49
45
|
|
50
46
|
|
@@ -52,8 +48,8 @@ class GuiWordList(QDialog):
|
|
52
48
|
|
53
49
|
newWordListReady = pyqtSignal()
|
54
50
|
|
55
|
-
def __init__(self,
|
56
|
-
super().__init__(parent=
|
51
|
+
def __init__(self, parent: QWidget) -> None:
|
52
|
+
super().__init__(parent=parent)
|
57
53
|
|
58
54
|
logger.debug("Create: GuiWordList")
|
59
55
|
self.setObjectName("GuiWordList")
|
@@ -257,5 +253,3 @@ class GuiWordList(QDialog):
|
|
257
253
|
if (item := self.listBox.item(i)) and (word := item.text().strip()):
|
258
254
|
result.append(word)
|
259
255
|
return result
|
260
|
-
|
261
|
-
# END Class GuiWordList
|
novelwriter/enum.py
CHANGED
@@ -32,8 +32,6 @@ class nwItemType(Enum):
|
|
32
32
|
FOLDER = 2
|
33
33
|
FILE = 3
|
34
34
|
|
35
|
-
# END Enum nwItemType
|
36
|
-
|
37
35
|
|
38
36
|
class nwItemClass(Enum):
|
39
37
|
|
@@ -50,8 +48,6 @@ class nwItemClass(Enum):
|
|
50
48
|
TEMPLATE = 10
|
51
49
|
TRASH = 11
|
52
50
|
|
53
|
-
# END Enum nwItemClass
|
54
|
-
|
55
51
|
|
56
52
|
class nwItemLayout(Enum):
|
57
53
|
|
@@ -59,16 +55,17 @@ class nwItemLayout(Enum):
|
|
59
55
|
DOCUMENT = 1
|
60
56
|
NOTE = 2
|
61
57
|
|
62
|
-
# END Enum nwItemLayout
|
63
|
-
|
64
58
|
|
65
59
|
class nwComment(Enum):
|
66
60
|
|
67
61
|
PLAIN = 0
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
IGNORE = 1
|
63
|
+
SYNOPSIS = 2
|
64
|
+
SHORT = 3
|
65
|
+
NOTE = 4
|
66
|
+
FOOTNOTE = 5
|
67
|
+
COMMENT = 6
|
68
|
+
STORY = 7
|
72
69
|
|
73
70
|
|
74
71
|
class nwTrinary(Enum):
|
@@ -77,16 +74,12 @@ class nwTrinary(Enum):
|
|
77
74
|
NEUTRAL = 0
|
78
75
|
POSITIVE = 1
|
79
76
|
|
80
|
-
# END Enum nwTrinary
|
81
|
-
|
82
77
|
|
83
78
|
class nwDocMode(Enum):
|
84
79
|
|
85
80
|
VIEW = 0
|
86
81
|
EDIT = 1
|
87
82
|
|
88
|
-
# END Enum nwDocMode
|
89
|
-
|
90
83
|
|
91
84
|
class nwDocAction(Enum):
|
92
85
|
|
@@ -129,8 +122,6 @@ class nwDocAction(Enum):
|
|
129
122
|
SC_SUP = 36
|
130
123
|
SC_SUB = 37
|
131
124
|
|
132
|
-
# END Enum nwDocAction
|
133
|
-
|
134
125
|
|
135
126
|
class nwDocInsert(Enum):
|
136
127
|
|
@@ -145,8 +136,7 @@ class nwDocInsert(Enum):
|
|
145
136
|
VSPACE_S = 8
|
146
137
|
VSPACE_M = 9
|
147
138
|
LIPSUM = 10
|
148
|
-
|
149
|
-
# END Enum nwDocInsert
|
139
|
+
FOOTNOTE = 11
|
150
140
|
|
151
141
|
|
152
142
|
class nwView(Enum):
|
@@ -157,8 +147,6 @@ class nwView(Enum):
|
|
157
147
|
OUTLINE = 3
|
158
148
|
SEARCH = 4
|
159
149
|
|
160
|
-
# END Enum nwView
|
161
|
-
|
162
150
|
|
163
151
|
class nwWidget(Enum):
|
164
152
|
|
@@ -167,8 +155,6 @@ class nwWidget(Enum):
|
|
167
155
|
VIEWER = 3
|
168
156
|
OUTLINE = 4
|
169
157
|
|
170
|
-
# END Enum nwWidget
|
171
|
-
|
172
158
|
|
173
159
|
class nwOutline(Enum):
|
174
160
|
|
@@ -190,8 +176,6 @@ class nwOutline(Enum):
|
|
190
176
|
CUSTOM = 15
|
191
177
|
SYNOP = 16
|
192
178
|
|
193
|
-
# END Enum nwOutline
|
194
|
-
|
195
179
|
|
196
180
|
class nwBuildFmt(Enum):
|
197
181
|
|
@@ -204,4 +188,26 @@ class nwBuildFmt(Enum):
|
|
204
188
|
J_HTML = 6
|
205
189
|
J_NWD = 7
|
206
190
|
|
207
|
-
|
191
|
+
|
192
|
+
class nwStatusShape(Enum):
|
193
|
+
|
194
|
+
SQUARE = 0
|
195
|
+
TRIANGLE = 1
|
196
|
+
NABLA = 2
|
197
|
+
DIAMOND = 3
|
198
|
+
PENTAGON = 4
|
199
|
+
HEXAGON = 5
|
200
|
+
STAR = 6
|
201
|
+
PACMAN = 7
|
202
|
+
CIRCLE_Q = 8
|
203
|
+
CIRCLE_H = 9
|
204
|
+
CIRCLE_T = 10
|
205
|
+
CIRCLE = 11
|
206
|
+
BARS_1 = 12
|
207
|
+
BARS_2 = 13
|
208
|
+
BARS_3 = 14
|
209
|
+
BARS_4 = 15
|
210
|
+
BLOCK_1 = 16
|
211
|
+
BLOCK_2 = 17
|
212
|
+
BLOCK_3 = 18
|
213
|
+
BLOCK_4 = 19
|
novelwriter/error.py
CHANGED
@@ -23,17 +23,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
23
|
"""
|
24
24
|
from __future__ import annotations
|
25
25
|
|
26
|
-
import sys
|
27
|
-
import random
|
28
26
|
import logging
|
27
|
+
import random
|
28
|
+
import sys
|
29
29
|
|
30
30
|
from typing import TYPE_CHECKING
|
31
31
|
|
32
32
|
from PyQt5.QtCore import Qt, pyqtSlot
|
33
33
|
from PyQt5.QtGui import QFont, QFontDatabase
|
34
34
|
from PyQt5.QtWidgets import (
|
35
|
-
QApplication,
|
36
|
-
|
35
|
+
QApplication, QDialog, QDialogButtonBox, QGridLayout, QLabel,
|
36
|
+
QPlainTextEdit, QStyle, QWidget
|
37
37
|
)
|
38
38
|
|
39
39
|
if TYPE_CHECKING: # pragma: no cover
|
@@ -42,10 +42,6 @@ if TYPE_CHECKING: # pragma: no cover
|
|
42
42
|
logger = logging.getLogger(__name__)
|
43
43
|
|
44
44
|
|
45
|
-
# =============================================================================================== #
|
46
|
-
# Utility Functions
|
47
|
-
# =============================================================================================== #
|
48
|
-
|
49
45
|
def logException() -> None:
|
50
46
|
"""Log the content of an exception message."""
|
51
47
|
exType, exValue, _ = sys.exc_info()
|
@@ -61,10 +57,6 @@ def formatException(exc: BaseException) -> str:
|
|
61
57
|
return f"{type(exc).__name__}: {str(exc)}"
|
62
58
|
|
63
59
|
|
64
|
-
# =============================================================================================== #
|
65
|
-
# Error Handler
|
66
|
-
# =============================================================================================== #
|
67
|
-
|
68
60
|
class NWErrorMessage(QDialog):
|
69
61
|
|
70
62
|
def __init__(self, parent: QWidget) -> None:
|
@@ -125,9 +117,11 @@ class NWErrorMessage(QDialog):
|
|
125
117
|
error traceback.
|
126
118
|
"""
|
127
119
|
from traceback import format_tb
|
120
|
+
|
121
|
+
from PyQt5.QtCore import PYQT_VERSION_STR, QT_VERSION_STR, QSysInfo
|
122
|
+
|
128
123
|
from novelwriter import __version__
|
129
124
|
from novelwriter.constants import nwConst
|
130
|
-
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QSysInfo
|
131
125
|
|
132
126
|
self.msgHead.setText(
|
133
127
|
"<p>An unhandled error has been encountered.</p>"
|
@@ -175,12 +169,11 @@ class NWErrorMessage(QDialog):
|
|
175
169
|
self.close()
|
176
170
|
return
|
177
171
|
|
178
|
-
# END Class NWErrorMessage
|
179
|
-
|
180
172
|
|
181
173
|
def exceptionHandler(exType: type, exValue: BaseException, exTrace: TracebackType) -> None:
|
182
174
|
"""Function to catch unhandled global exceptions."""
|
183
175
|
from traceback import print_tb
|
176
|
+
|
184
177
|
from PyQt5.QtWidgets import QApplication
|
185
178
|
|
186
179
|
logger.critical("%s: %s", exType.__name__, str(exValue))
|
@@ -26,11 +26,12 @@ from __future__ import annotations
|
|
26
26
|
from math import ceil
|
27
27
|
|
28
28
|
from PyQt5.QtCore import QRect
|
29
|
-
from PyQt5.QtGui import QBrush, QColor,
|
30
|
-
from PyQt5.QtWidgets import QProgressBar,
|
29
|
+
from PyQt5.QtGui import QBrush, QColor, QPainter, QPaintEvent, QPen
|
30
|
+
from PyQt5.QtWidgets import QProgressBar, QWidget
|
31
31
|
|
32
32
|
from novelwriter.types import (
|
33
|
-
|
33
|
+
QtAlignCenter, QtPaintAnitAlias, QtRoundCap, QtSizeFixed, QtSolidLine,
|
34
|
+
QtTransparent
|
34
35
|
)
|
35
36
|
|
36
37
|
|
@@ -59,7 +60,7 @@ class NProgressCircle(QProgressBar):
|
|
59
60
|
bar=self.palette().highlight().color(),
|
60
61
|
text=self.palette().text().color()
|
61
62
|
)
|
62
|
-
self.setSizePolicy(
|
63
|
+
self.setSizePolicy(QtSizeFixed, QtSizeFixed)
|
63
64
|
self.setFixedWidth(size)
|
64
65
|
self.setFixedHeight(size)
|
65
66
|
return
|
@@ -100,5 +101,3 @@ class NProgressCircle(QProgressBar):
|
|
100
101
|
painter.setPen(self._tColor)
|
101
102
|
painter.drawText(self._cRect, QtAlignCenter, self._text or f"{progress:.1f} %")
|
102
103
|
return
|
103
|
-
|
104
|
-
# END Class NProgressCircle
|
@@ -27,8 +27,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
27
27
|
"""
|
28
28
|
from __future__ import annotations
|
29
29
|
|
30
|
-
from PyQt5.QtGui import QColor, QFont, QPalette
|
31
30
|
from PyQt5.QtCore import Qt
|
31
|
+
from PyQt5.QtGui import QColor, QFont, QPalette
|
32
32
|
from PyQt5.QtWidgets import (
|
33
33
|
QAbstractButton, QFrame, QHBoxLayout, QLabel, QLayout, QScrollArea,
|
34
34
|
QVBoxLayout, QWidget
|
@@ -64,8 +64,6 @@ class NFixedPage(QFrame):
|
|
64
64
|
self.setLayout(layout)
|
65
65
|
return
|
66
66
|
|
67
|
-
# END Class NFixedPage
|
68
|
-
|
69
67
|
|
70
68
|
class NScrollablePage(QScrollArea):
|
71
69
|
"""Extension: Scrollable Page Widget
|
@@ -89,8 +87,6 @@ class NScrollablePage(QScrollArea):
|
|
89
87
|
self._widget.setLayout(layout)
|
90
88
|
return
|
91
89
|
|
92
|
-
# END Class NScrollablePage
|
93
|
-
|
94
90
|
|
95
91
|
class NScrollableForm(QScrollArea):
|
96
92
|
"""Extension: Scrollable Form Widget
|
@@ -184,16 +180,26 @@ class NScrollableForm(QScrollArea):
|
|
184
180
|
self._sections[identifier] = qLabel
|
185
181
|
return
|
186
182
|
|
187
|
-
def addRow(self, label: str, widget: QWidget, helpText: str = "",
|
188
|
-
button: QWidget | None = None, editable: str | None = None,
|
183
|
+
def addRow(self, label: str, widget: QWidget | list[QWidget], helpText: str = "",
|
184
|
+
unit: str | None = None, button: QWidget | None = None, editable: str | None = None,
|
189
185
|
stretch: tuple[int, int] = (1, 0)) -> None:
|
190
186
|
"""Add a label and a widget as a new row of the form."""
|
191
187
|
row = QHBoxLayout()
|
192
188
|
row.setSpacing(CONFIG.pxInt(12))
|
193
189
|
|
190
|
+
if isinstance(widget, list):
|
191
|
+
wBox = QHBoxLayout()
|
192
|
+
wBox.setContentsMargins(0, 0, 0, 0)
|
193
|
+
for item in widget:
|
194
|
+
wBox.addWidget(item)
|
195
|
+
qWidget = QWidget(self)
|
196
|
+
qWidget.setLayout(wBox)
|
197
|
+
else:
|
198
|
+
qWidget = widget
|
199
|
+
|
194
200
|
qLabel = QLabel(label, self)
|
195
201
|
qLabel.setIndent(self._indent)
|
196
|
-
qLabel.setBuddy(
|
202
|
+
qLabel.setBuddy(qWidget)
|
197
203
|
|
198
204
|
if helpText:
|
199
205
|
qHelp = NColourLabel(
|
@@ -212,19 +218,19 @@ class NScrollableForm(QScrollArea):
|
|
212
218
|
|
213
219
|
if isinstance(unit, str):
|
214
220
|
box = QHBoxLayout()
|
215
|
-
box.addWidget(
|
221
|
+
box.addWidget(qWidget, 1)
|
216
222
|
box.addWidget(QLabel(unit, self), 0)
|
217
223
|
row.addLayout(box, stretch[1])
|
218
224
|
elif isinstance(button, QAbstractButton):
|
219
225
|
box = QHBoxLayout()
|
220
|
-
box.addWidget(
|
226
|
+
box.addWidget(qWidget, 1)
|
221
227
|
box.addWidget(button, 0)
|
222
228
|
row.addLayout(box, stretch[1])
|
223
229
|
else:
|
224
|
-
row.addWidget(
|
230
|
+
row.addWidget(qWidget, stretch[1])
|
225
231
|
|
226
232
|
self._layout.addLayout(row)
|
227
|
-
self._index[label.strip()] =
|
233
|
+
self._index[label.strip()] = qWidget
|
228
234
|
self._first = False
|
229
235
|
|
230
236
|
return
|
@@ -235,8 +241,6 @@ class NScrollableForm(QScrollArea):
|
|
235
241
|
self._layout.addStretch(1)
|
236
242
|
return
|
237
243
|
|
238
|
-
# END Class NScrollableForm
|
239
|
-
|
240
244
|
|
241
245
|
class NColourLabel(QLabel):
|
242
246
|
"""Extension: A Coloured Label
|
@@ -267,8 +271,6 @@ class NColourLabel(QLabel):
|
|
267
271
|
|
268
272
|
return
|
269
273
|
|
270
|
-
# END Class NColourLabel
|
271
|
-
|
272
274
|
|
273
275
|
class NWrappedWidgetBox(QHBoxLayout):
|
274
276
|
"""Extension: A Text-Wrapped Widget Box
|
@@ -287,5 +289,3 @@ class NWrappedWidgetBox(QHBoxLayout):
|
|
287
289
|
if after:
|
288
290
|
self.addWidget(QLabel(after.lstrip()))
|
289
291
|
return
|
290
|
-
|
291
|
-
# END Class NWrappedWidgetBox
|
@@ -24,8 +24,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
24
24
|
"""
|
25
25
|
from __future__ import annotations
|
26
26
|
|
27
|
-
from PyQt5.QtGui import QStatusTipEvent, QWheelEvent
|
28
27
|
from PyQt5.QtCore import QEvent, QObject
|
28
|
+
from PyQt5.QtGui import QStatusTipEvent, QWheelEvent
|
29
29
|
from PyQt5.QtWidgets import QWidget
|
30
30
|
|
31
31
|
|
@@ -63,13 +63,9 @@ class WheelEventFilter(QObject):
|
|
63
63
|
self._locked = False
|
64
64
|
return False
|
65
65
|
|
66
|
-
# END Class WheelEventFilter
|
67
|
-
|
68
66
|
|
69
67
|
class StatusTipFilter(QObject):
|
70
68
|
|
71
69
|
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
72
70
|
"""Filter out status tip events on menus."""
|
73
71
|
return True if isinstance(event, QStatusTipEvent) else super().eventFilter(obj, event)
|
74
|
-
|
75
|
-
# END Class StatusTipFilter
|
@@ -6,6 +6,8 @@ File History:
|
|
6
6
|
Created: 2024-02-01 [2.3b1] NComboBox
|
7
7
|
Created: 2024-02-01 [2.3b1] NSpinBox
|
8
8
|
Created: 2024-02-01 [2.3b1] NDoubleSpinBox
|
9
|
+
Created: 2024-05-01 [2.5b1] NToolDialog
|
10
|
+
Created: 2024-05-01 [2.5b1] NNonBlockingDialog
|
9
11
|
|
10
12
|
This file is a part of novelWriter
|
11
13
|
Copyright 2018–2024, Veronica Berglyd Olsen
|
@@ -25,11 +27,56 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
27
|
"""
|
26
28
|
from __future__ import annotations
|
27
29
|
|
30
|
+
from enum import Enum
|
31
|
+
from typing import TYPE_CHECKING
|
32
|
+
|
28
33
|
from PyQt5.QtCore import QSize, Qt
|
29
34
|
from PyQt5.QtGui import QWheelEvent
|
30
|
-
from PyQt5.QtWidgets import
|
35
|
+
from PyQt5.QtWidgets import (
|
36
|
+
QApplication, QComboBox, QDialog, QDoubleSpinBox, QSpinBox, QToolButton,
|
37
|
+
QWidget
|
38
|
+
)
|
39
|
+
|
40
|
+
from novelwriter import CONFIG, SHARED
|
41
|
+
|
42
|
+
if TYPE_CHECKING: # pragma: no cover
|
43
|
+
from novelwriter.guimain import GuiMain
|
44
|
+
|
45
|
+
|
46
|
+
class NToolDialog(QDialog):
|
47
|
+
|
48
|
+
def __init__(self, parent: GuiMain) -> None:
|
49
|
+
super().__init__(parent=parent)
|
50
|
+
self.setModal(False)
|
51
|
+
if CONFIG.osDarwin:
|
52
|
+
self.setWindowFlag(Qt.WindowType.Tool)
|
53
|
+
return
|
54
|
+
|
55
|
+
def activateDialog(self) -> None:
|
56
|
+
"""Helper function to activate dialog on various systems."""
|
57
|
+
self.show()
|
58
|
+
if CONFIG.osWindows:
|
59
|
+
self.activateWindow()
|
60
|
+
self.raise_()
|
61
|
+
QApplication.processEvents()
|
62
|
+
return
|
63
|
+
|
31
64
|
|
32
|
-
|
65
|
+
class NNonBlockingDialog(QDialog):
|
66
|
+
|
67
|
+
def __init__(self, parent: QWidget | None = None) -> None:
|
68
|
+
super().__init__(parent=parent)
|
69
|
+
self.setModal(True)
|
70
|
+
return
|
71
|
+
|
72
|
+
def activateDialog(self) -> None:
|
73
|
+
"""Helper function to activate dialog on various systems."""
|
74
|
+
self.show()
|
75
|
+
if CONFIG.osWindows:
|
76
|
+
self.activateWindow()
|
77
|
+
self.raise_()
|
78
|
+
QApplication.processEvents()
|
79
|
+
return
|
33
80
|
|
34
81
|
|
35
82
|
class NComboBox(QComboBox):
|
@@ -46,14 +93,12 @@ class NComboBox(QComboBox):
|
|
46
93
|
event.ignore()
|
47
94
|
return
|
48
95
|
|
49
|
-
def setCurrentData(self, data: str, default: str) -> None:
|
96
|
+
def setCurrentData(self, data: str | int | Enum, default: str | int | Enum) -> None:
|
50
97
|
"""Set the current index from data, with a fallback."""
|
51
98
|
idx = self.findData(data)
|
52
99
|
self.setCurrentIndex(self.findData(default) if idx < 0 else idx)
|
53
100
|
return
|
54
101
|
|
55
|
-
# END Class NComboBox
|
56
|
-
|
57
102
|
|
58
103
|
class NSpinBox(QSpinBox):
|
59
104
|
|
@@ -69,8 +114,6 @@ class NSpinBox(QSpinBox):
|
|
69
114
|
event.ignore()
|
70
115
|
return
|
71
116
|
|
72
|
-
# END Class NSpinBox
|
73
|
-
|
74
117
|
|
75
118
|
class NDoubleSpinBox(QDoubleSpinBox):
|
76
119
|
|
@@ -86,8 +129,6 @@ class NDoubleSpinBox(QDoubleSpinBox):
|
|
86
129
|
event.ignore()
|
87
130
|
return
|
88
131
|
|
89
|
-
# END Class NDoubleSpinBox
|
90
|
-
|
91
132
|
|
92
133
|
class NIconToolButton(QToolButton):
|
93
134
|
|
@@ -105,8 +146,6 @@ class NIconToolButton(QToolButton):
|
|
105
146
|
self.setIcon(SHARED.theme.getIcon(iconKey))
|
106
147
|
return
|
107
148
|
|
108
|
-
# END Class NIconToolButton
|
109
|
-
|
110
149
|
|
111
150
|
class NIconToggleButton(QToolButton):
|
112
151
|
|
@@ -126,5 +165,3 @@ class NIconToggleButton(QToolButton):
|
|
126
165
|
iconSize = self.iconSize()
|
127
166
|
self.setIcon(SHARED.theme.getToggleIcon(iconKey, (iconSize.width(), iconSize.height())))
|
128
167
|
return
|
129
|
-
|
130
|
-
# END Class NUnfoldButton
|
@@ -29,8 +29,8 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
|
29
29
|
from PyQt5.QtWidgets import QComboBox, QWidget
|
30
30
|
|
31
31
|
from novelwriter import SHARED
|
32
|
-
from novelwriter.enum import nwItemClass
|
33
32
|
from novelwriter.constants import nwLabels
|
33
|
+
from novelwriter.enum import nwItemClass
|
34
34
|
|
35
35
|
logger = logging.getLogger(__name__)
|
36
36
|
|
@@ -126,5 +126,3 @@ class NovelSelector(QComboBox):
|
|
126
126
|
if not self._blockSignal:
|
127
127
|
self.novelSelectionChanged.emit(self.currentData())
|
128
128
|
return
|
129
|
-
|
130
|
-
# END Class NovelSelector
|
@@ -25,14 +25,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
25
25
|
"""
|
26
26
|
from __future__ import annotations
|
27
27
|
|
28
|
-
from PyQt5.QtGui import QColor, QPaintEvent, QPainter, QPolygon
|
29
28
|
from PyQt5.QtCore import QPoint, QRectF, QSize, Qt, pyqtSignal, pyqtSlot
|
29
|
+
from PyQt5.QtGui import QColor, QPainter, QPaintEvent, QPolygon
|
30
30
|
from PyQt5.QtWidgets import (
|
31
|
-
QAbstractButton, QAction, QButtonGroup, QLabel,
|
31
|
+
QAbstractButton, QAction, QButtonGroup, QLabel, QStyle,
|
32
32
|
QStyleOptionToolButton, QToolBar, QToolButton, QWidget
|
33
33
|
)
|
34
34
|
|
35
|
-
from novelwriter.types import
|
35
|
+
from novelwriter.types import (
|
36
|
+
QtAlignLeft, QtMouseOver, QtNoBrush, QtNoPen, QtPaintAnitAlias,
|
37
|
+
QtSizeExpanding, QtSizeFixed
|
38
|
+
)
|
36
39
|
|
37
40
|
|
38
41
|
class NPagedSideBar(QToolBar):
|
@@ -59,7 +62,7 @@ class NPagedSideBar(QToolBar):
|
|
59
62
|
self.setOrientation(Qt.Orientation.Vertical)
|
60
63
|
|
61
64
|
stretch = QWidget(self)
|
62
|
-
stretch.setSizePolicy(
|
65
|
+
stretch.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
|
63
66
|
self._stretchAction = self.addWidget(stretch)
|
64
67
|
|
65
68
|
return
|
@@ -109,8 +112,6 @@ class NPagedSideBar(QToolBar):
|
|
109
112
|
self.buttonClicked.emit(buttonId)
|
110
113
|
return
|
111
114
|
|
112
|
-
# END Class NPagedSideBar
|
113
|
-
|
114
115
|
|
115
116
|
class _NPagedToolButton(QToolButton):
|
116
117
|
|
@@ -119,7 +120,7 @@ class _NPagedToolButton(QToolButton):
|
|
119
120
|
def __init__(self, parent: QWidget) -> None:
|
120
121
|
super().__init__(parent=parent)
|
121
122
|
|
122
|
-
self.setSizePolicy(
|
123
|
+
self.setSizePolicy(QtSizeExpanding, QtSizeFixed)
|
123
124
|
self.setCheckable(True)
|
124
125
|
|
125
126
|
fH = self.fontMetrics().height()
|
@@ -187,8 +188,6 @@ class _NPagedToolButton(QToolButton):
|
|
187
188
|
|
188
189
|
return
|
189
190
|
|
190
|
-
# END Class _NPagedToolButton
|
191
|
-
|
192
191
|
|
193
192
|
class _NPagedToolLabel(QLabel):
|
194
193
|
|
@@ -197,7 +196,7 @@ class _NPagedToolLabel(QLabel):
|
|
197
196
|
def __init__(self, parent: QWidget, textColor: QColor | None = None) -> None:
|
198
197
|
super().__init__(parent=parent)
|
199
198
|
|
200
|
-
self.setSizePolicy(
|
199
|
+
self.setSizePolicy(QtSizeExpanding, QtSizeFixed)
|
201
200
|
|
202
201
|
fH = self.fontMetrics().height()
|
203
202
|
self._bH = round(fH * 1.7)
|
@@ -228,5 +227,3 @@ class _NPagedToolLabel(QLabel):
|
|
228
227
|
paint.drawText(QRectF(self._lM, self._tM, tW, tH), QtAlignLeft, self.text())
|
229
228
|
|
230
229
|
return
|
231
|
-
|
232
|
-
# END Class _NPagedToolLabel
|
@@ -25,7 +25,7 @@ from __future__ import annotations
|
|
25
25
|
|
26
26
|
from math import ceil
|
27
27
|
|
28
|
-
from PyQt5.QtGui import
|
28
|
+
from PyQt5.QtGui import QPainter, QPaintEvent
|
29
29
|
from PyQt5.QtWidgets import QProgressBar, QWidget
|
30
30
|
|
31
31
|
from novelwriter.types import QtPaintAnitAlias
|
@@ -51,5 +51,3 @@ class NProgressSimple(QProgressBar):
|
|
51
51
|
painter.setBrush(self.palette().highlight())
|
52
52
|
painter.drawRect(0, 0, progress, self.height())
|
53
53
|
return
|
54
|
-
|
55
|
-
# END Class NProgressSimple
|
@@ -27,7 +27,7 @@ import logging
|
|
27
27
|
|
28
28
|
from typing import Literal
|
29
29
|
|
30
|
-
from PyQt5.QtGui import QColor,
|
30
|
+
from PyQt5.QtGui import QColor, QPainter, QPaintEvent
|
31
31
|
from PyQt5.QtWidgets import QAbstractButton, QWidget
|
32
32
|
|
33
33
|
from novelwriter.types import QtPaintAnitAlias
|
@@ -75,5 +75,3 @@ class StatusLED(QAbstractButton):
|
|
75
75
|
painter.setOpacity(1.0)
|
76
76
|
painter.drawEllipse(1, 1, self.width() - 2, self.height() - 2)
|
77
77
|
return
|
78
|
-
|
79
|
-
# END Class StatusLED
|
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 PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent
|
27
26
|
from PyQt5.QtCore import QEvent, QPropertyAnimation, Qt, pyqtProperty
|
28
|
-
from PyQt5.
|
27
|
+
from PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent
|
28
|
+
from PyQt5.QtWidgets import QAbstractButton, QWidget
|
29
29
|
|
30
30
|
from novelwriter import CONFIG, SHARED
|
31
|
-
from novelwriter.types import
|
31
|
+
from novelwriter.types import QtMouseLeft, QtNoPen, QtPaintAnitAlias, QtSizeFixed
|
32
32
|
|
33
33
|
|
34
34
|
class NSwitch(QAbstractButton):
|
@@ -46,7 +46,7 @@ class NSwitch(QAbstractButton):
|
|
46
46
|
self._rR = self._xR - self._rB
|
47
47
|
|
48
48
|
self.setCheckable(True)
|
49
|
-
self.setSizePolicy(
|
49
|
+
self.setSizePolicy(QtSizeFixed, QtSizeFixed)
|
50
50
|
self.setFixedWidth(self._xW)
|
51
51
|
self.setFixedHeight(self._xH)
|
52
52
|
self._offset = self._xR
|
@@ -133,5 +133,3 @@ class NSwitch(QAbstractButton):
|
|
133
133
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
134
134
|
super().enterEvent(event)
|
135
135
|
return
|
136
|
-
|
137
|
-
# END Class NSwitch
|
@@ -23,12 +23,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
23
|
"""
|
24
24
|
from __future__ import annotations
|
25
25
|
|
26
|
-
from PyQt5.QtGui import QIcon
|
27
26
|
from PyQt5.QtCore import pyqtSignal
|
28
|
-
from PyQt5.
|
27
|
+
from PyQt5.QtGui import QIcon
|
28
|
+
from PyQt5.QtWidgets import QGridLayout, QLabel, QScrollArea, QWidget
|
29
29
|
|
30
30
|
from novelwriter.extensions.switch import NSwitch
|
31
|
-
from novelwriter.types import
|
31
|
+
from novelwriter.types import (
|
32
|
+
QtAlignLeft, QtAlignRight, QtAlignRightMiddle, QtSizeMinimum,
|
33
|
+
QtSizeMinimumExpanding
|
34
|
+
)
|
32
35
|
|
33
36
|
|
34
37
|
class NSwitchBox(QScrollArea):
|
@@ -59,7 +62,7 @@ class NSwitchBox(QScrollArea):
|
|
59
62
|
self._content.setColumnStretch(1, 1)
|
60
63
|
|
61
64
|
self._widget = QWidget(self)
|
62
|
-
self._widget.setSizePolicy(
|
65
|
+
self._widget.setSizePolicy(QtSizeMinimumExpanding, QtSizeMinimum)
|
63
66
|
self._widget.setLayout(self._content)
|
64
67
|
|
65
68
|
self.setWidgetResizable(True)
|
@@ -124,5 +127,3 @@ class NSwitchBox(QScrollArea):
|
|
124
127
|
self._content.setRowStretch(self._index + 1, 1)
|
125
128
|
self._index += 1
|
126
129
|
return
|
127
|
-
|
128
|
-
# END Class NSwitchBox
|