novelWriter 2.3rc1__py3-none-any.whl → 2.4__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.3rc1.dist-info → novelWriter-2.4.dist-info}/METADATA +5 -6
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/RECORD +119 -109
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/WHEEL +1 -1
- novelWriter-2.4.dist-info/entry_points.txt +2 -0
- novelwriter/__init__.py +17 -10
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_nl_NL.json +11 -0
- novelwriter/assets/i18n/project_pt_BR.json +11 -0
- novelwriter/assets/icons/none.svg +4 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_times.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_times.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tango.conf +23 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +25 -23
- novelwriter/assets/themes/cyberpunk_night.conf +29 -0
- novelwriter/common.py +12 -4
- novelwriter/config.py +47 -16
- novelwriter/constants.py +5 -6
- novelwriter/core/buildsettings.py +64 -44
- novelwriter/core/coretools.py +97 -13
- novelwriter/core/docbuild.py +74 -7
- novelwriter/core/document.py +24 -3
- novelwriter/core/index.py +31 -112
- novelwriter/core/project.py +11 -15
- novelwriter/core/projectxml.py +3 -2
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +3 -3
- novelwriter/core/status.py +6 -5
- novelwriter/core/storage.py +16 -6
- novelwriter/core/tohtml.py +22 -25
- novelwriter/core/tokenizer.py +417 -237
- novelwriter/core/tomd.py +17 -8
- novelwriter/core/toodt.py +386 -351
- novelwriter/core/tree.py +8 -8
- novelwriter/dialogs/about.py +10 -12
- novelwriter/dialogs/docmerge.py +17 -14
- novelwriter/dialogs/docsplit.py +20 -19
- novelwriter/dialogs/editlabel.py +5 -4
- novelwriter/dialogs/preferences.py +32 -40
- novelwriter/dialogs/projectsettings.py +31 -28
- novelwriter/dialogs/quotes.py +10 -9
- novelwriter/dialogs/wordlist.py +18 -15
- novelwriter/enum.py +17 -14
- novelwriter/error.py +14 -12
- novelwriter/extensions/circularprogress.py +12 -8
- novelwriter/extensions/configlayout.py +23 -3
- novelwriter/extensions/modified.py +51 -2
- novelwriter/extensions/pagedsidebar.py +16 -14
- novelwriter/extensions/simpleprogress.py +3 -1
- novelwriter/extensions/statusled.py +3 -1
- novelwriter/extensions/switch.py +10 -9
- novelwriter/extensions/switchbox.py +14 -13
- novelwriter/extensions/versioninfo.py +1 -1
- novelwriter/gui/doceditor.py +433 -496
- novelwriter/gui/dochighlight.py +54 -33
- novelwriter/gui/docviewer.py +162 -175
- novelwriter/gui/docviewerpanel.py +20 -37
- novelwriter/gui/editordocument.py +15 -4
- novelwriter/gui/itemdetails.py +51 -54
- novelwriter/gui/mainmenu.py +37 -17
- novelwriter/gui/noveltree.py +31 -37
- novelwriter/gui/outline.py +120 -98
- novelwriter/gui/projtree.py +114 -112
- novelwriter/gui/search.py +362 -0
- novelwriter/gui/sidebar.py +36 -45
- novelwriter/gui/statusbar.py +14 -14
- novelwriter/gui/theme.py +116 -34
- novelwriter/guimain.py +216 -207
- novelwriter/shared.py +31 -6
- novelwriter/text/counting.py +138 -0
- novelwriter/tools/dictionaries.py +15 -14
- novelwriter/tools/lipsum.py +20 -17
- novelwriter/tools/manusbuild.py +43 -35
- novelwriter/tools/manuscript.py +381 -104
- novelwriter/tools/manussettings.py +263 -125
- novelwriter/tools/noveldetails.py +21 -19
- novelwriter/tools/welcome.py +59 -57
- novelwriter/tools/writingstats.py +61 -55
- novelwriter/types.py +90 -0
- novelWriter-2.3rc1.dist-info/entry_points.txt +0 -5
- novelwriter/core/__init__.py +0 -3
- novelwriter/dialogs/__init__.py +0 -3
- novelwriter/extensions/__init__.py +0 -3
- novelwriter/gui/__init__.py +0 -3
- novelwriter/tools/__init__.py +0 -3
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/top_level.txt +0 -0
novelwriter/gui/theme.py
CHANGED
@@ -29,20 +29,24 @@ import logging
|
|
29
29
|
from math import ceil
|
30
30
|
from pathlib import Path
|
31
31
|
|
32
|
-
from PyQt5.QtCore import Qt
|
33
|
-
from PyQt5.QtWidgets import qApp
|
32
|
+
from PyQt5.QtCore import QSize, Qt
|
34
33
|
from PyQt5.QtGui import (
|
35
34
|
QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap
|
36
35
|
)
|
36
|
+
from PyQt5.QtWidgets import QApplication
|
37
37
|
|
38
38
|
from novelwriter import CONFIG
|
39
|
+
from novelwriter.common import NWConfigParser, cssCol, minmax
|
40
|
+
from novelwriter.constants import nwLabels
|
39
41
|
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
40
42
|
from novelwriter.error import logException
|
41
|
-
from novelwriter.common import NWConfigParser, minmax
|
42
|
-
from novelwriter.constants import nwLabels
|
43
43
|
|
44
44
|
logger = logging.getLogger(__name__)
|
45
45
|
|
46
|
+
STYLES_FLAT_TABS = "flatTabWidget"
|
47
|
+
STYLES_MIN_TOOLBUTTON = "minimalToolButton"
|
48
|
+
STYLES_BIG_TOOLBUTTON = "bigToolButton"
|
49
|
+
|
46
50
|
|
47
51
|
# =============================================================================================== #
|
48
52
|
# Gui Theme Class
|
@@ -70,9 +74,9 @@ class GuiTheme:
|
|
70
74
|
self.isLightTheme = True
|
71
75
|
|
72
76
|
# GUI
|
73
|
-
self.statNone = QColor(
|
74
|
-
self.statUnsaved = QColor(
|
75
|
-
self.statSaved = QColor(
|
77
|
+
self.statNone = QColor(0, 0, 0)
|
78
|
+
self.statUnsaved = QColor(0, 0, 0)
|
79
|
+
self.statSaved = QColor(0, 0, 0)
|
76
80
|
self.helpText = QColor(0, 0, 0)
|
77
81
|
|
78
82
|
# Loaded Syntax Settings
|
@@ -106,6 +110,7 @@ class GuiTheme:
|
|
106
110
|
self.colError = QColor(0, 0, 0)
|
107
111
|
self.colRepTag = QColor(0, 0, 0)
|
108
112
|
self.colMod = QColor(0, 0, 0)
|
113
|
+
self.colMark = QColor(255, 255, 255, 128)
|
109
114
|
|
110
115
|
# Class Setup
|
111
116
|
# ===========
|
@@ -119,6 +124,7 @@ class GuiTheme:
|
|
119
124
|
self._syntaxList: list[tuple[str, str]] = []
|
120
125
|
self._availThemes: dict[str, Path] = {}
|
121
126
|
self._availSyntax: dict[str, Path] = {}
|
127
|
+
self._styleSheets: dict[str, str] = {}
|
122
128
|
|
123
129
|
self._listConf(self._availSyntax, CONFIG.assetPath("syntax"))
|
124
130
|
self._listConf(self._availThemes, CONFIG.assetPath("themes"))
|
@@ -138,31 +144,42 @@ class GuiTheme:
|
|
138
144
|
self.getHeaderDecorationNarrow = self.iconCache.getHeaderDecorationNarrow
|
139
145
|
|
140
146
|
# Extract Other Info
|
141
|
-
self.guiDPI =
|
142
|
-
self.guiScale =
|
147
|
+
self.guiDPI = QApplication.primaryScreen().logicalDotsPerInchX()
|
148
|
+
self.guiScale = QApplication.primaryScreen().logicalDotsPerInchX()/96.0
|
143
149
|
CONFIG.guiScale = self.guiScale
|
144
150
|
logger.debug("GUI DPI: %.1f", self.guiDPI)
|
145
151
|
logger.debug("GUI Scale: %.2f", self.guiScale)
|
146
152
|
|
147
153
|
# Fonts
|
148
|
-
self.guiFont =
|
154
|
+
self.guiFont = QApplication.font()
|
155
|
+
self.guiFontB = QApplication.font()
|
156
|
+
self.guiFontB.setBold(True)
|
149
157
|
|
150
158
|
qMetric = QFontMetrics(self.guiFont)
|
159
|
+
fHeight = qMetric.height()
|
160
|
+
fAscent = qMetric.ascent()
|
151
161
|
self.fontPointSize = self.guiFont.pointSizeF()
|
152
|
-
self.fontPixelSize = int(round(
|
153
|
-
self.
|
162
|
+
self.fontPixelSize = int(round(fHeight))
|
163
|
+
self.baseIconHeight = int(round(fAscent))
|
164
|
+
self.baseButtonHeight = int(round(1.35*fAscent))
|
154
165
|
self.textNHeight = qMetric.boundingRect("N").height()
|
155
166
|
self.textNWidth = qMetric.boundingRect("N").width()
|
156
167
|
|
168
|
+
self.baseIconSize = QSize(self.baseIconHeight, self.baseIconHeight)
|
169
|
+
self.buttonIconSize = QSize(int(0.9*self.baseIconHeight), int(0.9*self.baseIconHeight))
|
170
|
+
|
157
171
|
# Monospace Font
|
158
172
|
self.guiFontFixed = QFont()
|
159
173
|
self.guiFontFixed.setPointSizeF(0.95*self.fontPointSize)
|
160
|
-
self.guiFontFixed.setFamily(
|
174
|
+
self.guiFontFixed.setFamily(
|
175
|
+
QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont).family()
|
176
|
+
)
|
161
177
|
|
162
178
|
logger.debug("GUI Font Family: %s", self.guiFont.family())
|
163
179
|
logger.debug("GUI Font Point Size: %.2f", self.fontPointSize)
|
164
180
|
logger.debug("GUI Font Pixel Size: %d", self.fontPixelSize)
|
165
|
-
logger.debug("GUI Base Icon
|
181
|
+
logger.debug("GUI Base Icon Height: %d", self.baseIconHeight)
|
182
|
+
logger.debug("GUI Base Button Height: %d", self.baseButtonHeight)
|
166
183
|
logger.debug("Text 'N' Height: %d", self.textNHeight)
|
167
184
|
logger.debug("Text 'N' Width: %d", self.textNWidth)
|
168
185
|
|
@@ -210,6 +227,10 @@ class GuiTheme:
|
|
210
227
|
logException()
|
211
228
|
return False
|
212
229
|
|
230
|
+
# Reset Palette
|
231
|
+
self._guiPalette = QApplication.style().standardPalette()
|
232
|
+
self._resetGuiColors()
|
233
|
+
|
213
234
|
# Main
|
214
235
|
sec = "Main"
|
215
236
|
if parser.has_section(sec):
|
@@ -239,8 +260,6 @@ class GuiTheme:
|
|
239
260
|
self._setPalette(parser, sec, "highlightedtext", QPalette.ColorRole.HighlightedText)
|
240
261
|
self._setPalette(parser, sec, "link", QPalette.ColorRole.Link)
|
241
262
|
self._setPalette(parser, sec, "linkvisited", QPalette.ColorRole.LinkVisited)
|
242
|
-
else:
|
243
|
-
self._guiPalette = qApp.style().standardPalette()
|
244
263
|
|
245
264
|
# GUI
|
246
265
|
sec = "GUI"
|
@@ -269,7 +288,10 @@ class GuiTheme:
|
|
269
288
|
self.iconCache.loadTheme(self.themeIcons or defaultIcons)
|
270
289
|
|
271
290
|
# Apply Styles
|
272
|
-
|
291
|
+
QApplication.setPalette(self._guiPalette)
|
292
|
+
|
293
|
+
# Reset stylesheets so that they are regenerated
|
294
|
+
self._buildStyleSheets(self._guiPalette)
|
273
295
|
|
274
296
|
return True
|
275
297
|
|
@@ -329,6 +351,7 @@ class GuiTheme:
|
|
329
351
|
self.colError = self._parseColour(confParser, cnfSec, "errorline")
|
330
352
|
self.colRepTag = self._parseColour(confParser, cnfSec, "replacetag")
|
331
353
|
self.colMod = self._parseColour(confParser, cnfSec, "modifier")
|
354
|
+
self.colMark = self._parseColour(confParser, cnfSec, "texthighlight")
|
332
355
|
|
333
356
|
return True
|
334
357
|
|
@@ -344,7 +367,7 @@ class GuiTheme:
|
|
344
367
|
if themeName:
|
345
368
|
self._themeList.append((themeKey, themeName))
|
346
369
|
|
347
|
-
self._themeList = sorted(self._themeList, key=
|
370
|
+
self._themeList = sorted(self._themeList, key=_sortTheme)
|
348
371
|
|
349
372
|
return self._themeList
|
350
373
|
|
@@ -360,14 +383,26 @@ class GuiTheme:
|
|
360
383
|
if syntaxName:
|
361
384
|
self._syntaxList.append((syntaxKey, syntaxName))
|
362
385
|
|
363
|
-
self._syntaxList = sorted(self._syntaxList, key=
|
386
|
+
self._syntaxList = sorted(self._syntaxList, key=_sortTheme)
|
364
387
|
|
365
388
|
return self._syntaxList
|
366
389
|
|
390
|
+
def getStyleSheet(self, name: str) -> str:
|
391
|
+
"""Load a standard style sheet."""
|
392
|
+
return self._styleSheets.get(name, "")
|
393
|
+
|
367
394
|
##
|
368
395
|
# Internal Functions
|
369
396
|
##
|
370
397
|
|
398
|
+
def _resetGuiColors(self) -> None:
|
399
|
+
"""Reset GUI colours to default values."""
|
400
|
+
self.statNone = QColor(120, 120, 120)
|
401
|
+
self.statUnsaved = QColor(200, 15, 39)
|
402
|
+
self.statSaved = QColor(2, 133, 37)
|
403
|
+
self.helpText = QColor(0, 0, 0)
|
404
|
+
return
|
405
|
+
|
371
406
|
def _setGuiFont(self) -> None:
|
372
407
|
"""Update the GUI's font style from settings."""
|
373
408
|
font = QFont()
|
@@ -378,14 +413,14 @@ class GuiTheme:
|
|
378
413
|
font.setFamily("Arial")
|
379
414
|
font.setPointSize(10)
|
380
415
|
else:
|
381
|
-
font = fontDB.systemFont(QFontDatabase.GeneralFont)
|
416
|
+
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
|
382
417
|
CONFIG.guiFont = font.family()
|
383
418
|
CONFIG.guiFontSize = font.pointSize()
|
384
419
|
else:
|
385
420
|
font.setFamily(CONFIG.guiFont)
|
386
421
|
font.setPointSize(CONFIG.guiFontSize)
|
387
422
|
|
388
|
-
|
423
|
+
QApplication.setFont(font)
|
389
424
|
|
390
425
|
return
|
391
426
|
|
@@ -410,6 +445,41 @@ class GuiTheme:
|
|
410
445
|
self._guiPalette.setColor(value, self._parseColour(parser, section, name))
|
411
446
|
return
|
412
447
|
|
448
|
+
def _buildStyleSheets(self, palette: QPalette) -> None:
|
449
|
+
"""Build default style sheets."""
|
450
|
+
self._styleSheets = {}
|
451
|
+
|
452
|
+
aPx = CONFIG.pxInt(2)
|
453
|
+
bPx = CONFIG.pxInt(4)
|
454
|
+
cPx = CONFIG.pxInt(6)
|
455
|
+
dPx = CONFIG.pxInt(8)
|
456
|
+
|
457
|
+
tCol = palette.text().color()
|
458
|
+
hCol = palette.highlight().color()
|
459
|
+
|
460
|
+
# Flat Tab Widget and Tab Bar:
|
461
|
+
self._styleSheets[STYLES_FLAT_TABS] = (
|
462
|
+
"QTabWidget::pane {border: 0;} "
|
463
|
+
f"QTabWidget QTabBar::tab {{border: 0; padding: {bPx}px {dPx}px;}} "
|
464
|
+
f"QTabWidget QTabBar::tab:selected {{color: {cssCol(hCol)};}} "
|
465
|
+
)
|
466
|
+
|
467
|
+
# Minimal Tool Button
|
468
|
+
self._styleSheets[STYLES_MIN_TOOLBUTTON] = (
|
469
|
+
f"QToolButton {{padding: {aPx}px; margin: 0; border: none; background: transparent;}} "
|
470
|
+
f"QToolButton:hover {{border: none; background: {cssCol(tCol, 48)};}} "
|
471
|
+
"QToolButton::menu-indicator {image: none;} "
|
472
|
+
)
|
473
|
+
|
474
|
+
# Big Tool Button
|
475
|
+
self._styleSheets[STYLES_BIG_TOOLBUTTON] = (
|
476
|
+
f"QToolButton {{padding: {cPx}px; margin: 0; border: none; background: transparent;}} "
|
477
|
+
f"QToolButton:hover {{border: none; background: {cssCol(tCol, 48)};}} "
|
478
|
+
"QToolButton::menu-indicator {image: none;} "
|
479
|
+
)
|
480
|
+
|
481
|
+
return
|
482
|
+
|
413
483
|
# End Class GuiTheme
|
414
484
|
|
415
485
|
|
@@ -437,7 +507,7 @@ class GuiIcons:
|
|
437
507
|
"build_excluded", "build_filtered", "build_included", "proj_chapter", "proj_details",
|
438
508
|
"proj_document", "proj_folder", "proj_note", "proj_nwx", "proj_section", "proj_scene",
|
439
509
|
"proj_stats", "proj_title", "status_idle", "status_lang", "status_lines", "status_stats",
|
440
|
-
"status_time", "view_build", "view_editor", "view_novel", "view_outline",
|
510
|
+
"status_time", "view_build", "view_editor", "view_novel", "view_outline", "view_search",
|
441
511
|
|
442
512
|
# Class Icons
|
443
513
|
"cls_archive", "cls_character", "cls_custom", "cls_entity", "cls_none", "cls_novel",
|
@@ -448,8 +518,8 @@ class GuiIcons:
|
|
448
518
|
"search_regex", "search_word",
|
449
519
|
|
450
520
|
# Format Icons
|
451
|
-
"fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "
|
452
|
-
"fmt_subscript", "fmt_superscript", "fmt_underline",
|
521
|
+
"fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_mark", "fmt_strike",
|
522
|
+
"fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline",
|
453
523
|
|
454
524
|
# General Button Icons
|
455
525
|
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross",
|
@@ -460,6 +530,7 @@ class GuiIcons:
|
|
460
530
|
# Switches
|
461
531
|
"sticky-on", "sticky-off",
|
462
532
|
"bullet-on", "bullet-off",
|
533
|
+
"unfold-show", "unfold-hide",
|
463
534
|
|
464
535
|
# Decorations
|
465
536
|
"deco_doc_h0", "deco_doc_h1", "deco_doc_h2", "deco_doc_h3", "deco_doc_h4", "deco_doc_more",
|
@@ -470,6 +541,7 @@ class GuiIcons:
|
|
470
541
|
TOGGLE_ICON_KEYS: dict[str, tuple[str, str]] = {
|
471
542
|
"sticky": ("sticky-on", "sticky-off"),
|
472
543
|
"bullet": ("bullet-on", "bullet-off"),
|
544
|
+
"unfold": ("unfold-show", "unfold-hide"),
|
473
545
|
}
|
474
546
|
|
475
547
|
IMAGE_MAP: dict[str, tuple[str, str]] = {
|
@@ -491,6 +563,9 @@ class GuiIcons:
|
|
491
563
|
self._confName = "icons.conf"
|
492
564
|
self._iconPath = CONFIG.assetPath("icons")
|
493
565
|
|
566
|
+
# None Icon
|
567
|
+
self._noIcon = QIcon(str(self._iconPath / "none.svg"))
|
568
|
+
|
494
569
|
# Icon Theme Meta
|
495
570
|
self.themeName = ""
|
496
571
|
self.themeDescription = ""
|
@@ -621,13 +696,13 @@ class GuiIcons:
|
|
621
696
|
def getToggleIcon(self, name: str, size: tuple[int, int]) -> QIcon:
|
622
697
|
"""Return a toggle icon from the icon buffer. or load it."""
|
623
698
|
if name in self.TOGGLE_ICON_KEYS:
|
624
|
-
pOne
|
699
|
+
pOne = self.getPixmap(self.TOGGLE_ICON_KEYS[name][0], size)
|
625
700
|
pTwo = self.getPixmap(self.TOGGLE_ICON_KEYS[name][1], size)
|
626
701
|
icon = QIcon()
|
627
702
|
icon.addPixmap(pOne, QIcon.Mode.Normal, QIcon.State.On)
|
628
703
|
icon.addPixmap(pTwo, QIcon.Mode.Normal, QIcon.State.Off)
|
629
704
|
return icon
|
630
|
-
return
|
705
|
+
return self._noIcon
|
631
706
|
|
632
707
|
def getPixmap(self, name: str, size: tuple[int, int]) -> QPixmap:
|
633
708
|
"""Return an icon from the icon buffer as a QPixmap. If it
|
@@ -638,7 +713,7 @@ class GuiIcons:
|
|
638
713
|
def getItemIcon(self, tType: nwItemType, tClass: nwItemClass,
|
639
714
|
tLayout: nwItemLayout, hLevel: str = "H0") -> QIcon:
|
640
715
|
"""Get the correct icon for a project item based on type, class
|
641
|
-
and
|
716
|
+
and heading level
|
642
717
|
"""
|
643
718
|
iconName = None
|
644
719
|
if tType == nwItemType.ROOT:
|
@@ -659,14 +734,14 @@ class GuiIcons:
|
|
659
734
|
elif tLayout == nwItemLayout.NOTE:
|
660
735
|
iconName = "proj_note"
|
661
736
|
if iconName is None:
|
662
|
-
return
|
737
|
+
return self._noIcon
|
663
738
|
|
664
739
|
return self.getIcon(iconName)
|
665
740
|
|
666
741
|
def getHeaderDecoration(self, hLevel: int) -> QPixmap:
|
667
|
-
"""Get the decoration for a specific
|
742
|
+
"""Get the decoration for a specific heading level."""
|
668
743
|
if not self._headerDec:
|
669
|
-
iPx = self.mainTheme.
|
744
|
+
iPx = self.mainTheme.baseIconHeight
|
670
745
|
self._headerDec = [
|
671
746
|
self.loadDecoration("deco_doc_h0", h=iPx),
|
672
747
|
self.loadDecoration("deco_doc_h1", h=iPx),
|
@@ -677,9 +752,9 @@ class GuiIcons:
|
|
677
752
|
return self._headerDec[minmax(hLevel, 0, 4)]
|
678
753
|
|
679
754
|
def getHeaderDecorationNarrow(self, hLevel: int) -> QPixmap:
|
680
|
-
"""Get the narrow decoration for a specific
|
755
|
+
"""Get the narrow decoration for a specific heading level."""
|
681
756
|
if not self._headerDecNarrow:
|
682
|
-
iPx = self.mainTheme.
|
757
|
+
iPx = self.mainTheme.baseIconHeight
|
683
758
|
self._headerDecNarrow = [
|
684
759
|
self.loadDecoration("deco_doc_h0_n", h=iPx),
|
685
760
|
self.loadDecoration("deco_doc_h1_n", h=iPx),
|
@@ -700,7 +775,7 @@ class GuiIcons:
|
|
700
775
|
"""
|
701
776
|
if name not in self.ICON_KEYS:
|
702
777
|
logger.error("Requested unknown icon name '%s'", name)
|
703
|
-
return
|
778
|
+
return self._noIcon
|
704
779
|
|
705
780
|
# If we just want the app icons, return right away
|
706
781
|
if name == "novelwriter":
|
@@ -716,7 +791,7 @@ class GuiIcons:
|
|
716
791
|
# If we didn't find one, give up and return an empty icon
|
717
792
|
logger.warning("Did not load an icon for '%s'", name)
|
718
793
|
|
719
|
-
return
|
794
|
+
return self._noIcon
|
720
795
|
|
721
796
|
# END Class GuiIcons
|
722
797
|
|
@@ -725,6 +800,13 @@ class GuiIcons:
|
|
725
800
|
# Module Functions
|
726
801
|
# =============================================================================================== #
|
727
802
|
|
803
|
+
|
804
|
+
def _sortTheme(data: tuple[str, str]) -> str:
|
805
|
+
"""Key function for theme sorting."""
|
806
|
+
key, name = data
|
807
|
+
return f"*{name}" if key.startswith("default_") else name
|
808
|
+
|
809
|
+
|
728
810
|
def _loadInternalName(confParser: NWConfigParser, confFile: str | Path) -> str:
|
729
811
|
"""Open a conf file and read the 'name' setting."""
|
730
812
|
try:
|