novelWriter 2.2.1__py3-none-any.whl → 2.3__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 (125) hide show
  1. {novelWriter-2.2.1.dist-info → novelWriter-2.3.dist-info}/METADATA +1 -1
  2. {novelWriter-2.2.1.dist-info → novelWriter-2.3.dist-info}/RECORD +116 -101
  3. novelWriter-2.3.dist-info/entry_points.txt +2 -0
  4. novelwriter/__init__.py +4 -4
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  9. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  10. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  11. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  12. novelwriter/assets/i18n/project_nl_NL.json +11 -0
  13. novelwriter/assets/i18n/project_pt_BR.json +11 -0
  14. novelwriter/assets/icons/typicons_dark/icons.conf +8 -0
  15. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +6 -0
  16. novelwriter/assets/icons/typicons_dark/mixed_import.svg +5 -0
  17. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +4 -0
  18. novelwriter/assets/icons/typicons_dark/typ_document.svg +4 -0
  19. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +4 -0
  20. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +9 -0
  21. novelwriter/assets/icons/typicons_light/icons.conf +8 -0
  22. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +6 -0
  23. novelwriter/assets/icons/typicons_light/mixed_import.svg +5 -0
  24. novelwriter/assets/icons/typicons_light/typ_document-add.svg +4 -0
  25. novelwriter/assets/icons/typicons_light/typ_document.svg +4 -0
  26. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +4 -0
  27. novelwriter/assets/icons/typicons_light/typ_th-list.svg +9 -0
  28. novelwriter/assets/images/novelwriter-text-dark.svg +4 -0
  29. novelwriter/assets/images/novelwriter-text-light.svg +4 -0
  30. novelwriter/assets/images/welcome-dark.jpg +0 -0
  31. novelwriter/assets/images/welcome-light.jpg +0 -0
  32. novelwriter/assets/manual.pdf +0 -0
  33. novelwriter/assets/sample.zip +0 -0
  34. novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
  35. novelwriter/assets/syntax/default_dark.conf +1 -0
  36. novelwriter/assets/syntax/default_light.conf +1 -0
  37. novelwriter/assets/syntax/grey_dark.conf +1 -0
  38. novelwriter/assets/syntax/grey_light.conf +1 -0
  39. novelwriter/assets/syntax/light_owl.conf +1 -0
  40. novelwriter/assets/syntax/night_owl.conf +1 -0
  41. novelwriter/assets/syntax/solarized_dark.conf +1 -0
  42. novelwriter/assets/syntax/solarized_light.conf +1 -0
  43. novelwriter/assets/syntax/tango.conf +23 -0
  44. novelwriter/assets/syntax/tomorrow.conf +1 -0
  45. novelwriter/assets/syntax/tomorrow_night.conf +1 -0
  46. novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
  47. novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
  48. novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
  49. novelwriter/assets/text/credits_en.htm +4 -2
  50. novelwriter/assets/themes/cyberpunk_night.conf +29 -0
  51. novelwriter/assets/themes/default_dark.conf +2 -2
  52. novelwriter/assets/themes/default_light.conf +2 -2
  53. novelwriter/common.py +48 -37
  54. novelwriter/config.py +36 -41
  55. novelwriter/constants.py +38 -16
  56. novelwriter/core/buildsettings.py +7 -7
  57. novelwriter/core/coretools.py +196 -156
  58. novelwriter/core/docbuild.py +6 -3
  59. novelwriter/core/document.py +6 -6
  60. novelwriter/core/index.py +89 -56
  61. novelwriter/core/item.py +21 -3
  62. novelwriter/core/options.py +8 -7
  63. novelwriter/core/project.py +70 -44
  64. novelwriter/core/projectdata.py +1 -14
  65. novelwriter/core/projectxml.py +13 -41
  66. novelwriter/core/sessions.py +2 -1
  67. novelwriter/core/spellcheck.py +2 -1
  68. novelwriter/core/status.py +2 -1
  69. novelwriter/core/storage.py +182 -140
  70. novelwriter/core/tohtml.py +4 -2
  71. novelwriter/core/tokenizer.py +109 -82
  72. novelwriter/core/toodt.py +40 -30
  73. novelwriter/core/tree.py +3 -2
  74. novelwriter/dialogs/about.py +70 -160
  75. novelwriter/dialogs/docmerge.py +6 -5
  76. novelwriter/dialogs/docsplit.py +6 -6
  77. novelwriter/dialogs/editlabel.py +1 -1
  78. novelwriter/dialogs/preferences.py +553 -703
  79. novelwriter/dialogs/{projsettings.py → projectsettings.py} +288 -262
  80. novelwriter/dialogs/quotes.py +27 -23
  81. novelwriter/dialogs/wordlist.py +96 -40
  82. novelwriter/enum.py +20 -18
  83. novelwriter/error.py +1 -1
  84. novelwriter/extensions/circularprogress.py +11 -11
  85. novelwriter/extensions/configlayout.py +185 -134
  86. novelwriter/extensions/modified.py +81 -0
  87. novelwriter/extensions/novelselector.py +26 -12
  88. novelwriter/extensions/pagedsidebar.py +14 -16
  89. novelwriter/extensions/simpleprogress.py +5 -5
  90. novelwriter/extensions/statusled.py +8 -8
  91. novelwriter/extensions/switch.py +31 -63
  92. novelwriter/extensions/switchbox.py +1 -1
  93. novelwriter/extensions/versioninfo.py +153 -0
  94. novelwriter/gui/doceditor.py +178 -150
  95. novelwriter/gui/dochighlight.py +63 -92
  96. novelwriter/gui/docviewer.py +49 -51
  97. novelwriter/gui/docviewerpanel.py +72 -24
  98. novelwriter/gui/itemdetails.py +7 -7
  99. novelwriter/gui/mainmenu.py +14 -19
  100. novelwriter/gui/noveltree.py +9 -8
  101. novelwriter/gui/outline.py +98 -75
  102. novelwriter/gui/projtree.py +241 -106
  103. novelwriter/gui/sidebar.py +3 -4
  104. novelwriter/gui/statusbar.py +3 -4
  105. novelwriter/gui/theme.py +69 -70
  106. novelwriter/guimain.py +51 -156
  107. novelwriter/shared.py +15 -1
  108. novelwriter/tools/dictionaries.py +5 -6
  109. novelwriter/tools/manuscript.py +6 -6
  110. novelwriter/tools/manussettings.py +192 -221
  111. novelwriter/tools/noveldetails.py +525 -0
  112. novelwriter/tools/welcome.py +819 -0
  113. novelwriter/tools/writingstats.py +9 -9
  114. novelWriter-2.2.1.dist-info/entry_points.txt +0 -5
  115. novelwriter/assets/images/wizard-back.jpg +0 -0
  116. novelwriter/assets/text/gplv3_en.htm +0 -641
  117. novelwriter/assets/text/release_notes.htm +0 -60
  118. novelwriter/dialogs/projdetails.py +0 -518
  119. novelwriter/dialogs/projload.py +0 -294
  120. novelwriter/dialogs/updates.py +0 -172
  121. novelwriter/extensions/pageddialog.py +0 -130
  122. novelwriter/tools/projwizard.py +0 -478
  123. {novelWriter-2.2.1.dist-info → novelWriter-2.3.dist-info}/LICENSE.md +0 -0
  124. {novelWriter-2.2.1.dist-info → novelWriter-2.3.dist-info}/WHEEL +0 -0
  125. {novelWriter-2.2.1.dist-info → novelWriter-2.3.dist-info}/top_level.txt +0 -0
@@ -79,9 +79,9 @@ class GuiSideBar(QWidget):
79
79
  self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
80
80
 
81
81
  self.tbDetails = QToolButton(self)
82
- self.tbDetails.setToolTip("{0} [Shift+F6]".format(self.tr("Project Details")))
82
+ self.tbDetails.setToolTip("{0} [Shift+F6]".format(self.tr("Novel Details")))
83
83
  self.tbDetails.setIconSize(iconSize)
84
- self.tbDetails.clicked.connect(self.mainGui.showProjectDetailsDialog)
84
+ self.tbDetails.clicked.connect(self.mainGui.showNovelDetailsDialog)
85
85
 
86
86
  self.tbStats = QToolButton(self)
87
87
  self.tbStats.setToolTip("{0} [F6]".format(self.tr("Writing Statistics")))
@@ -167,8 +167,7 @@ class _PopRightMenu(QMenu):
167
167
  def event(self, event: QEvent) -> bool:
168
168
  """Overload the show event and move the menu popup location."""
169
169
  if event.type() == QEvent.Show:
170
- parent = self.parent()
171
- if isinstance(parent, QWidget):
170
+ if isinstance(parent := self.parent(), QWidget):
172
171
  offset = QPoint(parent.width(), parent.height() - self.height())
173
172
  self.move(parent.mapToGlobal(offset))
174
173
  return super(_PopRightMenu, self).event(event)
@@ -29,7 +29,6 @@ from time import time
29
29
  from typing import TYPE_CHECKING, Literal
30
30
  from datetime import datetime
31
31
 
32
- from PyQt5.QtGui import QColor
33
32
  from PyQt5.QtCore import pyqtSlot, QLocale
34
33
  from PyQt5.QtWidgets import qApp, QStatusBar, QLabel
35
34
 
@@ -55,9 +54,9 @@ class GuiMainStatus(QStatusBar):
55
54
  self._userIdle = False
56
55
  self._debugInfo = False
57
56
 
58
- colNone = QColor(*SHARED.theme.statNone)
59
- colSaved = QColor(*SHARED.theme.statSaved)
60
- colUnsaved = QColor(*SHARED.theme.statUnsaved)
57
+ colNone = SHARED.theme.statNone
58
+ colSaved = SHARED.theme.statSaved
59
+ colUnsaved = SHARED.theme.statUnsaved
61
60
 
62
61
  iPx = SHARED.theme.baseIconSize
63
62
 
novelwriter/gui/theme.py CHANGED
@@ -67,12 +67,13 @@ class GuiTheme:
67
67
  self.themeLicense = ""
68
68
  self.themeLicenseUrl = ""
69
69
  self.themeIcons = ""
70
+ self.isLightTheme = True
70
71
 
71
72
  # GUI
72
- self.statNone = [120, 120, 120]
73
- self.statUnsaved = [200, 15, 39]
74
- self.statSaved = [2, 133, 37]
75
- self.helpText = [0, 0, 0]
73
+ self.statNone = QColor(120, 120, 120)
74
+ self.statUnsaved = QColor(200, 15, 39)
75
+ self.statSaved = QColor(2, 133, 37)
76
+ self.helpText = QColor(0, 0, 0)
76
77
 
77
78
  # Loaded Syntax Settings
78
79
  # ======================
@@ -87,23 +88,24 @@ class GuiTheme:
87
88
  self.syntaxLicenseUrl = ""
88
89
 
89
90
  # Colours
90
- self.colBack = [255, 255, 255]
91
- self.colText = [0, 0, 0]
92
- self.colLink = [0, 0, 0]
93
- self.colHead = [0, 0, 0]
94
- self.colHeadH = [0, 0, 0]
95
- self.colEmph = [0, 0, 0]
96
- self.colDialN = [0, 0, 0]
97
- self.colDialD = [0, 0, 0]
98
- self.colDialS = [0, 0, 0]
99
- self.colHidden = [0, 0, 0]
100
- self.colCode = [0, 0, 0]
101
- self.colKey = [0, 0, 0]
102
- self.colVal = [0, 0, 0]
103
- self.colSpell = [0, 0, 0]
104
- self.colError = [0, 0, 0]
105
- self.colRepTag = [0, 0, 0]
106
- self.colMod = [0, 0, 0]
91
+ self.colBack = QColor(255, 255, 255)
92
+ self.colText = QColor(0, 0, 0)
93
+ self.colLink = QColor(0, 0, 0)
94
+ self.colHead = QColor(0, 0, 0)
95
+ self.colHeadH = QColor(0, 0, 0)
96
+ self.colEmph = QColor(0, 0, 0)
97
+ self.colDialN = QColor(0, 0, 0)
98
+ self.colDialD = QColor(0, 0, 0)
99
+ self.colDialS = QColor(0, 0, 0)
100
+ self.colHidden = QColor(0, 0, 0)
101
+ self.colCode = QColor(0, 0, 0)
102
+ self.colKey = QColor(0, 0, 0)
103
+ self.colVal = QColor(0, 0, 0)
104
+ self.colOpt = QColor(0, 0, 0)
105
+ self.colSpell = QColor(0, 0, 0)
106
+ self.colError = QColor(0, 0, 0)
107
+ self.colRepTag = QColor(0, 0, 0)
108
+ self.colMod = QColor(0, 0, 0)
107
109
 
108
110
  # Class Setup
109
111
  # ===========
@@ -112,7 +114,7 @@ class GuiTheme:
112
114
  self._setGuiFont()
113
115
 
114
116
  # Load Themes
115
- self._guiPalette = QPalette()
117
+ self._guiPalette = QPalette()
116
118
  self._themeList: list[tuple[str, str]] = []
117
119
  self._syntaxList: list[tuple[str, str]] = []
118
120
  self._availThemes: dict[str, Path] = {}
@@ -254,13 +256,13 @@ class GuiTheme:
254
256
 
255
257
  backLNess = backCol.lightnessF()
256
258
  textLNess = textCol.lightnessF()
257
-
258
- if self.helpText == [0, 0, 0]:
259
- if backLNess > textLNess:
259
+ self.isLightTheme = backLNess > textLNess
260
+ if self.helpText == QColor(0, 0, 0):
261
+ if self.isLightTheme:
260
262
  helpLCol = textLNess + 0.35*(backLNess - textLNess)
261
263
  else:
262
264
  helpLCol = backLNess + 0.65*(textLNess - backLNess)
263
- self.helpText = [int(255*helpLCol)]*3
265
+ self.helpText = QColor.fromHsl(0, 0, int(255*helpLCol))
264
266
 
265
267
  # Icons
266
268
  defaultIcons = "typicons_light" if backLNess >= 0.5 else "typicons_dark"
@@ -322,6 +324,7 @@ class GuiTheme:
322
324
  self.colCode = self._parseColour(confParser, cnfSec, "shortcode")
323
325
  self.colKey = self._parseColour(confParser, cnfSec, "keyword")
324
326
  self.colVal = self._parseColour(confParser, cnfSec, "value")
327
+ self.colOpt = self._parseColour(confParser, cnfSec, "optional")
325
328
  self.colSpell = self._parseColour(confParser, cnfSec, "spellcheckline")
326
329
  self.colError = self._parseColour(confParser, cnfSec, "errorline")
327
330
  self.colRepTag = self._parseColour(confParser, cnfSec, "replacetag")
@@ -341,7 +344,7 @@ class GuiTheme:
341
344
  if themeName:
342
345
  self._themeList.append((themeKey, themeName))
343
346
 
344
- self._themeList = sorted(self._themeList, key=lambda x: x[1])
347
+ self._themeList = sorted(self._themeList, key=_sortTheme)
345
348
 
346
349
  return self._themeList
347
350
 
@@ -357,7 +360,7 @@ class GuiTheme:
357
360
  if syntaxName:
358
361
  self._syntaxList.append((syntaxKey, syntaxName))
359
362
 
360
- self._syntaxList = sorted(self._syntaxList, key=lambda x: x[1])
363
+ self._syntaxList = sorted(self._syntaxList, key=_sortTheme)
361
364
 
362
365
  return self._syntaxList
363
366
 
@@ -367,22 +370,22 @@ class GuiTheme:
367
370
 
368
371
  def _setGuiFont(self) -> None:
369
372
  """Update the GUI's font style from settings."""
370
- theFont = QFont()
373
+ font = QFont()
371
374
  fontDB = QFontDatabase()
372
375
  if CONFIG.guiFont not in fontDB.families():
373
376
  if CONFIG.osWindows and "Arial" in fontDB.families():
374
377
  # On Windows we default to Arial if possible
375
- theFont.setFamily("Arial")
376
- theFont.setPointSize(10)
378
+ font.setFamily("Arial")
379
+ font.setPointSize(10)
377
380
  else:
378
- theFont = fontDB.systemFont(QFontDatabase.GeneralFont)
379
- CONFIG.guiFont = theFont.family()
380
- CONFIG.guiFontSize = theFont.pointSize()
381
+ font = fontDB.systemFont(QFontDatabase.GeneralFont)
382
+ CONFIG.guiFont = font.family()
383
+ CONFIG.guiFontSize = font.pointSize()
381
384
  else:
382
- theFont.setFamily(CONFIG.guiFont)
383
- theFont.setPointSize(CONFIG.guiFontSize)
385
+ font.setFamily(CONFIG.guiFont)
386
+ font.setPointSize(CONFIG.guiFontSize)
384
387
 
385
- qApp.setFont(theFont)
388
+ qApp.setFont(font)
386
389
 
387
390
  return
388
391
 
@@ -397,29 +400,14 @@ class GuiTheme:
397
400
 
398
401
  return True
399
402
 
400
- def _parseColour(self, parser: NWConfigParser, section: str, name: str) -> list[int]:
403
+ def _parseColour(self, parser: NWConfigParser, section: str, name: str) -> QColor:
401
404
  """Parse a colour value from a config string."""
402
- if parser.has_option(section, name):
403
- values = parser.get(section, name).split(",")
404
- result = []
405
- try:
406
- result.append(minmax(int(values[0]), 0, 255))
407
- result.append(minmax(int(values[1]), 0, 255))
408
- result.append(minmax(int(values[2]), 0, 255))
409
- except Exception:
410
- logger.error("Could not load theme colours for '%s' from config file", name)
411
- result = [0, 0, 0]
412
- else:
413
- logger.warning("Could not find theme colours for '%s' in config file", name)
414
- result = [0, 0, 0]
415
- return result
405
+ return QColor(*parser.rdIntList(section, name, [0, 0, 0, 255]))
416
406
 
417
407
  def _setPalette(self, parser: NWConfigParser, section: str,
418
408
  name: str, value: QPalette.ColorRole) -> None:
419
409
  """Set a palette colour value from a config string."""
420
- self._guiPalette.setColor(
421
- value, QColor(*self._parseColour(parser, section, name))
422
- )
410
+ self._guiPalette.setColor(value, self._parseColour(parser, section, name))
423
411
  return
424
412
 
425
413
  # End Class GuiTheme
@@ -443,7 +431,7 @@ class GuiIcons:
443
431
  missing, a blank icon is returned and a warning issued.
444
432
  """
445
433
 
446
- ICON_KEYS = {
434
+ ICON_KEYS: set[str] = {
447
435
  # Project and GUI Icons
448
436
  "novelwriter", "alert_error", "alert_info", "alert_question", "alert_warn",
449
437
  "build_excluded", "build_filtered", "build_included", "proj_chapter", "proj_details",
@@ -453,7 +441,7 @@ class GuiIcons:
453
441
 
454
442
  # Class Icons
455
443
  "cls_archive", "cls_character", "cls_custom", "cls_entity", "cls_none", "cls_novel",
456
- "cls_object", "cls_plot", "cls_timeline", "cls_trash", "cls_world",
444
+ "cls_object", "cls_plot", "cls_template", "cls_timeline", "cls_trash", "cls_world",
457
445
 
458
446
  # Search Icons
459
447
  "search_cancel", "search_case", "search_loop", "search_preserve", "search_project",
@@ -464,9 +452,10 @@ class GuiIcons:
464
452
  "fmt_subscript", "fmt_superscript", "fmt_underline",
465
453
 
466
454
  # General Button Icons
467
- "add", "backward", "bookmark", "browse", "checked", "close", "cross", "down", "edit",
468
- "export", "forward", "maximise", "menu", "minimise", "noncheckable", "panel", "refresh",
469
- "remove", "revert", "search_replace", "search", "settings", "unchecked", "up", "view",
455
+ "add", "add_document", "backward", "bookmark", "browse", "checked", "close", "cross",
456
+ "document", "down", "edit", "export", "forward", "import", "list", "maximise", "menu",
457
+ "minimise", "more", "noncheckable", "open", "panel", "refresh", "remove", "revert",
458
+ "search_replace", "search", "settings", "star", "unchecked", "up", "view",
470
459
 
471
460
  # Switches
472
461
  "sticky-on", "sticky-off",
@@ -478,13 +467,14 @@ class GuiIcons:
478
467
  "deco_doc_nt_n",
479
468
  }
480
469
 
481
- TOGGLE_ICON_KEYS = {
470
+ TOGGLE_ICON_KEYS: dict[str, tuple[str, str]] = {
482
471
  "sticky": ("sticky-on", "sticky-off"),
483
472
  "bullet": ("bullet-on", "bullet-off"),
484
473
  }
485
474
 
486
- IMAGE_MAP = {
487
- "wiz-back": "wizard-back.jpg",
475
+ IMAGE_MAP: dict[str, tuple[str, str]] = {
476
+ "welcome": ("welcome-light.jpg", "welcome-dark.jpg"),
477
+ "nw-text": ("novelwriter-text-light.svg", "novelwriter-text-dark.svg"),
488
478
  }
489
479
 
490
480
  def __init__(self, mainTheme: GuiTheme) -> None:
@@ -598,7 +588,8 @@ class GuiIcons:
598
588
  if name in self._themeMap:
599
589
  imgPath = self._themeMap[name]
600
590
  elif name in self.IMAGE_MAP:
601
- imgPath = CONFIG.assetPath("images") / self.IMAGE_MAP[name]
591
+ idx = 0 if self.mainTheme.isLightTheme else 1
592
+ imgPath = CONFIG.assetPath("images") / self.IMAGE_MAP[name][idx]
602
593
  else:
603
594
  logger.error("Decoration with name '%s' does not exist", name)
604
595
  return QPixmap()
@@ -608,12 +599,13 @@ class GuiIcons:
608
599
  return QPixmap()
609
600
 
610
601
  pixmap = QPixmap(str(imgPath))
602
+ tMode = Qt.TransformationMode.SmoothTransformation
611
603
  if w is not None and h is not None:
612
- return pixmap.scaled(w, h, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
604
+ return pixmap.scaled(w, h, Qt.AspectRatioMode.IgnoreAspectRatio, tMode)
613
605
  elif w is None and h is not None:
614
- return pixmap.scaledToHeight(h, Qt.SmoothTransformation)
606
+ return pixmap.scaledToHeight(h, tMode)
615
607
  elif w is not None and h is None:
616
- return pixmap.scaledToWidth(w, Qt.SmoothTransformation)
608
+ return pixmap.scaledToWidth(w, tMode)
617
609
 
618
610
  return pixmap
619
611
 
@@ -632,8 +624,8 @@ class GuiIcons:
632
624
  pOne = self.getPixmap(self.TOGGLE_ICON_KEYS[name][0], size)
633
625
  pTwo = self.getPixmap(self.TOGGLE_ICON_KEYS[name][1], size)
634
626
  icon = QIcon()
635
- icon.addPixmap(pOne, QIcon.Normal, QIcon.On)
636
- icon.addPixmap(pTwo, QIcon.Normal, QIcon.Off)
627
+ icon.addPixmap(pOne, QIcon.Mode.Normal, QIcon.State.On)
628
+ icon.addPixmap(pTwo, QIcon.Mode.Normal, QIcon.State.Off)
637
629
  return icon
638
630
  return QIcon()
639
631
 
@@ -641,7 +633,7 @@ class GuiIcons:
641
633
  """Return an icon from the icon buffer as a QPixmap. If it
642
634
  doesn't exist, return an empty QPixmap.
643
635
  """
644
- return self.getIcon(name).pixmap(size[0], size[1], QIcon.Normal)
636
+ return self.getIcon(name).pixmap(size[0], size[1], QIcon.Mode.Normal)
645
637
 
646
638
  def getItemIcon(self, tType: nwItemType, tClass: nwItemClass,
647
639
  tLayout: nwItemLayout, hLevel: str = "H0") -> QIcon:
@@ -733,6 +725,13 @@ class GuiIcons:
733
725
  # Module Functions
734
726
  # =============================================================================================== #
735
727
 
728
+
729
+ def _sortTheme(data: tuple[str, str]) -> str:
730
+ """Key function for theme sorting."""
731
+ key, name = data
732
+ return f"*{name}" if key.startswith("default_") else name
733
+
734
+
736
735
  def _loadInternalName(confParser: NWConfigParser, confFile: str | Path) -> str:
737
736
  """Open a conf file and read the 'name' setting."""
738
737
  try: