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.
Files changed (62) hide show
  1. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/METADATA +1 -1
  2. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/RECORD +61 -61
  3. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +3 -3
  5. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  6. novelwriter/assets/i18n/project_pt_BR.json +74 -74
  7. novelwriter/assets/manual.pdf +0 -0
  8. novelwriter/assets/sample.zip +0 -0
  9. novelwriter/assets/themes/cyberpunk_night.conf +1 -0
  10. novelwriter/assets/themes/default_dark.conf +1 -0
  11. novelwriter/assets/themes/default_light.conf +1 -0
  12. novelwriter/assets/themes/dracula.conf +1 -0
  13. novelwriter/assets/themes/solarized_dark.conf +1 -0
  14. novelwriter/assets/themes/solarized_light.conf +1 -0
  15. novelwriter/common.py +2 -3
  16. novelwriter/config.py +67 -15
  17. novelwriter/constants.py +8 -10
  18. novelwriter/core/buildsettings.py +5 -3
  19. novelwriter/core/coretools.py +3 -1
  20. novelwriter/core/docbuild.py +1 -0
  21. novelwriter/core/tohtml.py +69 -29
  22. novelwriter/core/tokenizer.py +83 -14
  23. novelwriter/core/toodt.py +48 -21
  24. novelwriter/core/toqdoc.py +25 -9
  25. novelwriter/dialogs/about.py +10 -15
  26. novelwriter/dialogs/docmerge.py +16 -16
  27. novelwriter/dialogs/docsplit.py +16 -16
  28. novelwriter/dialogs/editlabel.py +6 -8
  29. novelwriter/dialogs/preferences.py +94 -68
  30. novelwriter/dialogs/projectsettings.py +10 -10
  31. novelwriter/dialogs/quotes.py +9 -5
  32. novelwriter/dialogs/wordlist.py +6 -6
  33. novelwriter/enum.py +4 -5
  34. novelwriter/extensions/configlayout.py +23 -4
  35. novelwriter/extensions/modified.py +22 -3
  36. novelwriter/extensions/{circularprogress.py → progressbars.py} +26 -3
  37. novelwriter/extensions/statusled.py +28 -22
  38. novelwriter/gui/doceditor.py +20 -11
  39. novelwriter/gui/dochighlight.py +30 -39
  40. novelwriter/gui/docviewer.py +21 -14
  41. novelwriter/gui/mainmenu.py +11 -11
  42. novelwriter/gui/outline.py +3 -3
  43. novelwriter/gui/projtree.py +19 -28
  44. novelwriter/gui/search.py +10 -1
  45. novelwriter/gui/statusbar.py +25 -29
  46. novelwriter/gui/theme.py +3 -0
  47. novelwriter/guimain.py +91 -84
  48. novelwriter/shared.py +10 -8
  49. novelwriter/text/patterns.py +113 -0
  50. novelwriter/tools/dictionaries.py +2 -8
  51. novelwriter/tools/lipsum.py +8 -12
  52. novelwriter/tools/manusbuild.py +9 -9
  53. novelwriter/tools/manuscript.py +10 -5
  54. novelwriter/tools/manussettings.py +7 -3
  55. novelwriter/tools/noveldetails.py +10 -10
  56. novelwriter/tools/welcome.py +10 -10
  57. novelwriter/tools/writingstats.py +3 -3
  58. novelwriter/types.py +5 -2
  59. novelwriter/extensions/simpleprogress.py +0 -53
  60. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/LICENSE.md +0 -0
  61. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/entry_points.txt +0 -0
  62. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/top_level.txt +0 -0
@@ -30,7 +30,7 @@ from pathlib import Path
30
30
  from PyQt5.QtCore import QTimer, pyqtSlot
31
31
  from PyQt5.QtGui import QCloseEvent
32
32
  from PyQt5.QtWidgets import (
33
- QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog,
33
+ QAbstractButton, QAbstractItemView, QDialogButtonBox, QFileDialog,
34
34
  QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem,
35
35
  QPushButton, QSplitter, QVBoxLayout, QWidget
36
36
  )
@@ -42,14 +42,14 @@ from novelwriter.core.buildsettings import BuildSettings
42
42
  from novelwriter.core.docbuild import NWBuildDocument
43
43
  from novelwriter.core.item import NWItem
44
44
  from novelwriter.enum import nwBuildFmt
45
- from novelwriter.extensions.modified import NIconToolButton
46
- from novelwriter.extensions.simpleprogress import NProgressSimple
45
+ from novelwriter.extensions.modified import NDialog, NIconToolButton
46
+ from novelwriter.extensions.progressbars import NProgressSimple
47
47
  from novelwriter.types import QtAlignCenter, QtDialogClose, QtRoleAction, QtRoleReject, QtUserRole
48
48
 
49
49
  logger = logging.getLogger(__name__)
50
50
 
51
51
 
52
- class GuiManuscriptBuild(QDialog):
52
+ class GuiManuscriptBuild(NDialog):
53
53
  """GUI Tools: Manuscript Build Dialog
54
54
 
55
55
  This is the tool for running the build itself. It can be accessed
@@ -220,7 +220,7 @@ class GuiManuscriptBuild(QDialog):
220
220
 
221
221
  self.btnBuild.setFocus()
222
222
  self._populateContentList()
223
- self.buildPath.setText(str(self._build.lastPath))
223
+ self.buildPath.setText(str(self._build.lastBuildPath))
224
224
  if self._build.lastBuildName:
225
225
  self.buildName.setText(self._build.lastBuildName)
226
226
  else:
@@ -250,7 +250,7 @@ class GuiManuscriptBuild(QDialog):
250
250
  """
251
251
  self._saveSettings()
252
252
  event.accept()
253
- self.deleteLater()
253
+ self.softDelete()
254
254
  return
255
255
 
256
256
  ##
@@ -274,7 +274,7 @@ class GuiManuscriptBuild(QDialog):
274
274
  def _doSelectPath(self) -> None:
275
275
  """Select a folder for output."""
276
276
  bPath = Path(self.buildPath.text())
277
- bPath = bPath if bPath.is_dir() else self._build.lastPath
277
+ bPath = bPath if bPath.is_dir() else self._build.lastBuildPath
278
278
  savePath = QFileDialog.getExistingDirectory(
279
279
  self, self.tr("Select Folder"), str(bPath)
280
280
  )
@@ -327,7 +327,7 @@ class GuiManuscriptBuild(QDialog):
327
327
  return False
328
328
 
329
329
  # Make sure editor content is saved before we start
330
- SHARED.saveDocument()
330
+ SHARED.saveEditor()
331
331
 
332
332
  docBuild = NWBuildDocument(SHARED.project, self._build)
333
333
  docBuild.queueAll()
@@ -336,7 +336,7 @@ class GuiManuscriptBuild(QDialog):
336
336
  for i, _ in docBuild.iterBuild(buildPath, bFormat):
337
337
  self.buildProgress.setValue(i+1)
338
338
 
339
- self._build.setLastPath(bPath)
339
+ self._build.setLastBuildPath(bPath)
340
340
  self._build.setLastBuildName(bName)
341
341
  self._build.setLastFormat(bFormat)
342
342
 
@@ -44,8 +44,8 @@ from novelwriter.core.buildsettings import BuildCollection, BuildSettings
44
44
  from novelwriter.core.docbuild import NWBuildDocument
45
45
  from novelwriter.core.tokenizer import HeadingFormatter
46
46
  from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
47
- from novelwriter.extensions.circularprogress import NProgressCircle
48
47
  from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton, NToolDialog
48
+ from novelwriter.extensions.progressbars import NProgressCircle
49
49
  from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
50
50
  from novelwriter.tools.manusbuild import GuiManuscriptBuild
51
51
  from novelwriter.tools.manussettings import GuiBuildSettings
@@ -265,7 +265,7 @@ class GuiManuscript(NToolDialog):
265
265
  if isinstance(obj, GuiBuildSettings) and obj.isVisible():
266
266
  obj.close()
267
267
  event.accept()
268
- self.deleteLater()
268
+ self.softDelete()
269
269
  return
270
270
 
271
271
  ##
@@ -322,8 +322,10 @@ class GuiManuscript(NToolDialog):
322
322
  if not (build := self._getSelectedBuild()):
323
323
  return
324
324
 
325
+ start = time()
326
+
325
327
  # Make sure editor content is saved before we start
326
- SHARED.saveDocument()
328
+ SHARED.saveEditor()
327
329
 
328
330
  docBuild = NWBuildDocument(SHARED.project, build)
329
331
  docBuild.queueAll()
@@ -339,6 +341,8 @@ class GuiManuscript(NToolDialog):
339
341
  theme.keyword = QColor(245, 135, 31)
340
342
  theme.tag = QColor(66, 113, 174)
341
343
  theme.optional = QColor(66, 113, 174)
344
+ theme.dialog = QColor(66, 113, 174)
345
+ theme.altdialog = QColor(129, 55, 9)
342
346
 
343
347
  self.docPreview.beginNewBuild(len(docBuild))
344
348
  for step, _ in docBuild.iterBuildPreview(theme):
@@ -358,6 +362,8 @@ class GuiManuscript(NToolDialog):
358
362
  self.docStats.updateStats(buildObj.textStats)
359
363
  self.buildOutline.updateOutline(buildObj.textOutline)
360
364
 
365
+ logger.debug("Build completed in %.3f ms", 1000*(time()-start))
366
+
361
367
  return
362
368
 
363
369
  @pyqtSlot()
@@ -891,9 +897,8 @@ class _PreviewWidget(QTextBrowser):
891
897
  document within the viewport.
892
898
  """
893
899
  vBar = self.verticalScrollBar()
894
- sW = vBar.width() if vBar.isVisible() else 0
895
900
  tB = self.frameWidth()
896
- vW = self.width() - 2*tB - sW
901
+ vW = self.width() - 2*tB - vBar.width()
897
902
  vH = self.height() - 2*tB
898
903
  tH = self.ageLabel.height()
899
904
  pS = self.buildProgress.width()
@@ -98,8 +98,8 @@ class GuiBuildSettings(NToolDialog):
98
98
 
99
99
  # Title
100
100
  self.titleLabel = NColourLabel(
101
- self.tr("Manuscript Build Settings"), SHARED.theme.helpText,
102
- parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
101
+ self.tr("Manuscript Build Settings"), self, color=SHARED.theme.helpText,
102
+ scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
103
103
  )
104
104
 
105
105
  # Settings Name
@@ -200,7 +200,7 @@ class GuiBuildSettings(NToolDialog):
200
200
  self._askToSaveBuild()
201
201
  self._saveSettings()
202
202
  event.accept()
203
- self.deleteLater()
203
+ self.softDelete()
204
204
  return
205
205
 
206
206
  ##
@@ -1093,11 +1093,13 @@ class _FormatTab(NScrollableForm):
1093
1093
  self.stripUnicode = NSwitch(self, height=iPx)
1094
1094
  self.replaceTabs = NSwitch(self, height=iPx)
1095
1095
  self.keepBreaks = NSwitch(self, height=iPx)
1096
+ self.showDialogue = NSwitch(self, height=iPx)
1096
1097
 
1097
1098
  self.addRow(self._build.getLabel("format.justifyText"), self.justifyText)
1098
1099
  self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
1099
1100
  self.addRow(self._build.getLabel("format.replaceTabs"), self.replaceTabs)
1100
1101
  self.addRow(self._build.getLabel("format.keepBreaks"), self.keepBreaks)
1102
+ self.addRow(self._build.getLabel("format.showDialogue"), self.showDialogue)
1101
1103
 
1102
1104
  # First Line Indent
1103
1105
  # =================
@@ -1180,6 +1182,7 @@ class _FormatTab(NScrollableForm):
1180
1182
  self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
1181
1183
  self.replaceTabs.setChecked(self._build.getBool("format.replaceTabs"))
1182
1184
  self.keepBreaks.setChecked(self._build.getBool("format.keepBreaks"))
1185
+ self.showDialogue.setChecked(self._build.getBool("format.showDialogue"))
1183
1186
 
1184
1187
  self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
1185
1188
  self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
@@ -1219,6 +1222,7 @@ class _FormatTab(NScrollableForm):
1219
1222
  self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
1220
1223
  self._build.setValue("format.replaceTabs", self.replaceTabs.isChecked())
1221
1224
  self._build.setValue("format.keepBreaks", self.keepBreaks.isChecked())
1225
+ self._build.setValue("format.showDialogue", self.showDialogue.isChecked())
1222
1226
 
1223
1227
  self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
1224
1228
  self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
@@ -68,8 +68,8 @@ class GuiNovelDetails(NNonBlockingDialog):
68
68
 
69
69
  # Title
70
70
  self.titleLabel = NColourLabel(
71
- self.tr("Novel Details"), SHARED.theme.helpText,
72
- parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
71
+ self.tr("Novel Details"), self, color=SHARED.theme.helpText,
72
+ scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
73
73
  )
74
74
 
75
75
  # Novel Selector
@@ -97,7 +97,7 @@ class GuiNovelDetails(NNonBlockingDialog):
97
97
 
98
98
  # Buttons
99
99
  self.buttonBox = QDialogButtonBox(QtDialogClose, self)
100
- self.buttonBox.rejected.connect(self.close)
100
+ self.buttonBox.rejected.connect(self.reject)
101
101
 
102
102
  # Assemble
103
103
  self.topBox = QHBoxLayout()
@@ -150,7 +150,7 @@ class GuiNovelDetails(NNonBlockingDialog):
150
150
  """Capture the user closing the window and save settings."""
151
151
  self._saveSettings()
152
152
  event.accept()
153
- self.deleteLater()
153
+ self.softDelete()
154
154
  return
155
155
 
156
156
  ##
@@ -199,8 +199,8 @@ class _OverviewPage(NScrollablePage):
199
199
 
200
200
  # Project Info
201
201
  self.projLabel = NColourLabel(
202
- self.tr("Project"), SHARED.theme.helpText,
203
- parent=self, scale=NColourLabel.HEADER_SCALE
202
+ self.tr("Project"), self, color=SHARED.theme.helpText,
203
+ scale=NColourLabel.HEADER_SCALE
204
204
  )
205
205
 
206
206
  self.projName = QLabel("", self)
@@ -223,8 +223,8 @@ class _OverviewPage(NScrollablePage):
223
223
 
224
224
  # Novel Info
225
225
  self.novelLabel = NColourLabel(
226
- self.tr("Selected Novel"), SHARED.theme.helpText,
227
- parent=self, scale=NColourLabel.HEADER_SCALE
226
+ self.tr("Selected Novel"), self, color=SHARED.theme.helpText,
227
+ scale=NColourLabel.HEADER_SCALE
228
228
  )
229
229
 
230
230
  self.novelName = QLabel("", self)
@@ -315,8 +315,8 @@ class _ContentsPage(NFixedPage):
315
315
 
316
316
  # Title
317
317
  self.contentLabel = NColourLabel(
318
- self.tr("Table of Contents"), SHARED.theme.helpText,
319
- parent=self, scale=NColourLabel.HEADER_SCALE
318
+ self.tr("Table of Contents"), self, color=SHARED.theme.helpText,
319
+ scale=NColourLabel.HEADER_SCALE
320
320
  )
321
321
 
322
322
  # Contents Tree
@@ -34,8 +34,8 @@ from PyQt5.QtCore import (
34
34
  )
35
35
  from PyQt5.QtGui import QCloseEvent, QColor, QFont, QPainter, QPaintEvent, QPen
36
36
  from PyQt5.QtWidgets import (
37
- QAction, QApplication, QDialog, QFileDialog, QFormLayout, QHBoxLayout,
38
- QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
37
+ QAction, QApplication, QFileDialog, QFormLayout, QHBoxLayout, QLabel,
38
+ QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
39
39
  QStackedWidget, QStyledItemDelegate, QStyleOptionViewItem, QVBoxLayout,
40
40
  QWidget
41
41
  )
@@ -46,7 +46,7 @@ from novelwriter.constants import nwFiles
46
46
  from novelwriter.core.coretools import ProjectBuilder
47
47
  from novelwriter.enum import nwItemClass
48
48
  from novelwriter.extensions.configlayout import NWrappedWidgetBox
49
- from novelwriter.extensions.modified import NIconToolButton, NSpinBox
49
+ from novelwriter.extensions.modified import NDialog, NIconToolButton, NSpinBox
50
50
  from novelwriter.extensions.switch import NSwitch
51
51
  from novelwriter.extensions.versioninfo import VersionInfoWidget
52
52
  from novelwriter.types import QtAlignLeft, QtAlignRightTop, QtSelected
@@ -56,7 +56,7 @@ logger = logging.getLogger(__name__)
56
56
  PANEL_ALPHA = 178
57
57
 
58
58
 
59
- class GuiWelcome(QDialog):
59
+ class GuiWelcome(NDialog):
60
60
 
61
61
  openProjectRequest = pyqtSignal(Path)
62
62
 
@@ -196,7 +196,7 @@ class GuiWelcome(QDialog):
196
196
  """Capture the user closing the window and save settings."""
197
197
  self._saveSettings()
198
198
  event.accept()
199
- self.deleteLater()
199
+ self.softDelete()
200
200
  return
201
201
 
202
202
  ##
@@ -220,8 +220,7 @@ class GuiWelcome(QDialog):
220
220
  @pyqtSlot()
221
221
  def _browseForProject(self) -> None:
222
222
  """Browse for a project to open."""
223
- if path := SHARED.getProjectPath(self, path=CONFIG.lastPath(), allowZip=False):
224
- CONFIG.setLastPath(path)
223
+ if path := SHARED.getProjectPath(self, path=CONFIG.homePath(), allowZip=False):
225
224
  self._openProjectPath(path)
226
225
  return
227
226
 
@@ -550,7 +549,7 @@ class _NewProjectForm(QWidget):
550
549
  def __init__(self, parent: QWidget) -> None:
551
550
  super().__init__(parent=parent)
552
551
 
553
- self._basePath = CONFIG.homePath()
552
+ self._basePath = CONFIG.lastPath("project")
554
553
  self._fillMode = self.FILL_BLANK
555
554
  self._copyPath = None
556
555
 
@@ -726,12 +725,13 @@ class _NewProjectForm(QWidget):
726
725
  @pyqtSlot()
727
726
  def _doBrowse(self) -> None:
728
727
  """Select a project folder."""
729
- if projDir := QFileDialog.getExistingDirectory(
728
+ if path := QFileDialog.getExistingDirectory(
730
729
  self, self.tr("Select Project Folder"),
731
730
  str(self._basePath), options=QFileDialog.Option.ShowDirsOnly
732
731
  ):
733
- self._basePath = Path(projDir)
732
+ self._basePath = Path(path)
734
733
  self._updateProjPath()
734
+ CONFIG.setLastPath("project", path)
735
735
  return
736
736
 
737
737
  @pyqtSlot()
@@ -318,7 +318,7 @@ class GuiWritingStats(NToolDialog):
318
318
  def closeEvent(self, event: QCloseEvent) -> None:
319
319
  """Capture the user closing the window."""
320
320
  event.accept()
321
- self.deleteLater()
321
+ self.softDelete()
322
322
  return
323
323
 
324
324
  ##
@@ -384,14 +384,14 @@ class GuiWritingStats(NToolDialog):
384
384
  return False
385
385
 
386
386
  # Generate the file name
387
- savePath = CONFIG.lastPath() / f"sessionStats.{fileExt}"
387
+ savePath = CONFIG.lastPath("stats") / f"sessionStats.{fileExt}"
388
388
  savePath, _ = QFileDialog.getSaveFileName(
389
389
  self, self.tr("Save Data As"), str(savePath), f"{textFmt} (*.{fileExt})"
390
390
  )
391
391
  if not savePath:
392
392
  return False
393
393
 
394
- CONFIG.setLastPath(savePath)
394
+ CONFIG.setLastPath("stats", savePath)
395
395
 
396
396
  # Do the actual writing
397
397
  wSuccess = False
novelwriter/types.py CHANGED
@@ -25,7 +25,7 @@ from __future__ import annotations
25
25
 
26
26
  from PyQt5.QtCore import QRegularExpression, Qt
27
27
  from PyQt5.QtGui import QColor, QFont, QPainter, QTextCharFormat, QTextCursor, QTextFormat
28
- from PyQt5.QtWidgets import QDialogButtonBox, QSizePolicy, QStyle
28
+ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QSizePolicy, QStyle
29
29
 
30
30
  # Qt Alignment Flags
31
31
 
@@ -73,13 +73,16 @@ QtUserRole = Qt.ItemDataRole.UserRole
73
73
  # Keyboard and Mouse Buttons
74
74
 
75
75
  QtModCtrl = Qt.KeyboardModifier.ControlModifier
76
- QtModeNone = Qt.KeyboardModifier.NoModifier
76
+ QtModNone = Qt.KeyboardModifier.NoModifier
77
77
  QtModShift = Qt.KeyboardModifier.ShiftModifier
78
78
  QtMouseLeft = Qt.MouseButton.LeftButton
79
79
  QtMouseMiddle = Qt.MouseButton.MiddleButton
80
80
 
81
81
  # Dialog Button Box Types
82
82
 
83
+ QtAccepted = QDialog.DialogCode.Accepted
84
+ QtRejected = QDialog.DialogCode.Rejected
85
+
83
86
  QtDialogApply = QDialogButtonBox.StandardButton.Apply
84
87
  QtDialogCancel = QDialogButtonBox.StandardButton.Cancel
85
88
  QtDialogClose = QDialogButtonBox.StandardButton.Close
@@ -1,53 +0,0 @@
1
- """
2
- novelWriter – Custom Widget: Progress Simple
3
- ============================================
4
-
5
- File History:
6
- Created: 2023-06-09 [2.1b1]
7
-
8
- This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
10
-
11
- This program is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU General Public License as published by
13
- the Free Software Foundation, either version 3 of the License, or
14
- (at your option) any later version.
15
-
16
- This program is distributed in the hope that it will be useful, but
17
- WITHOUT ANY WARRANTY; without even the implied warranty of
18
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
- General Public License for more details.
20
-
21
- You should have received a copy of the GNU General Public License
22
- along with this program. If not, see <https://www.gnu.org/licenses/>.
23
- """
24
- from __future__ import annotations
25
-
26
- from math import ceil
27
-
28
- from PyQt5.QtGui import QPainter, QPaintEvent
29
- from PyQt5.QtWidgets import QProgressBar, QWidget
30
-
31
- from novelwriter.types import QtPaintAnitAlias
32
-
33
-
34
- class NProgressSimple(QProgressBar):
35
- """Extension: Simple Progress Widget
36
-
37
- A custom widget that paints a plain bar with no other styling.
38
- """
39
-
40
- def __init__(self, parent: QWidget) -> None:
41
- super().__init__(parent=parent)
42
- return
43
-
44
- def paintEvent(self, event: QPaintEvent) -> None:
45
- """Custom painter for the progress bar."""
46
- if (value := self.value()) > 0:
47
- progress = ceil(self.width()*float(value)/self.maximum())
48
- painter = QPainter(self)
49
- painter.setRenderHint(QtPaintAnitAlias, True)
50
- painter.setPen(self.palette().highlight().color())
51
- painter.setBrush(self.palette().highlight())
52
- painter.drawRect(0, 0, progress, self.height())
53
- return