novelWriter 2.5.3__py3-none-any.whl → 2.6b2__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.5.3.dist-info → novelWriter-2.6b2.dist-info}/METADATA +1 -1
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/RECORD +80 -60
- novelwriter/__init__.py +49 -10
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +8 -0
- novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
- novelwriter/assets/icons/typicons_light/icons.conf +8 -0
- novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/common.py +100 -2
- novelwriter/config.py +25 -15
- novelwriter/constants.py +168 -60
- novelwriter/core/buildsettings.py +66 -39
- novelwriter/core/coretools.py +145 -147
- novelwriter/core/docbuild.py +132 -170
- novelwriter/core/index.py +38 -37
- novelwriter/core/item.py +41 -8
- novelwriter/core/itemmodel.py +518 -0
- novelwriter/core/options.py +4 -1
- novelwriter/core/project.py +67 -89
- novelwriter/core/spellcheck.py +9 -14
- novelwriter/core/status.py +7 -5
- novelwriter/core/tree.py +268 -287
- novelwriter/dialogs/docmerge.py +7 -17
- novelwriter/dialogs/preferences.py +46 -33
- novelwriter/dialogs/projectsettings.py +5 -5
- novelwriter/enum.py +36 -23
- novelwriter/extensions/configlayout.py +27 -12
- novelwriter/extensions/modified.py +13 -1
- novelwriter/extensions/pagedsidebar.py +5 -5
- novelwriter/formats/shared.py +155 -0
- novelwriter/formats/todocx.py +1191 -0
- novelwriter/formats/tohtml.py +451 -0
- novelwriter/{core → formats}/tokenizer.py +487 -491
- novelwriter/formats/tomarkdown.py +217 -0
- novelwriter/{core → formats}/toodt.py +311 -432
- novelwriter/formats/toqdoc.py +484 -0
- novelwriter/formats/toraw.py +91 -0
- novelwriter/gui/doceditor.py +342 -284
- novelwriter/gui/dochighlight.py +96 -84
- novelwriter/gui/docviewer.py +88 -31
- novelwriter/gui/docviewerpanel.py +17 -25
- novelwriter/gui/editordocument.py +17 -2
- novelwriter/gui/itemdetails.py +25 -28
- novelwriter/gui/mainmenu.py +129 -63
- novelwriter/gui/noveltree.py +45 -47
- novelwriter/gui/outline.py +196 -249
- novelwriter/gui/projtree.py +594 -1241
- novelwriter/gui/search.py +9 -10
- novelwriter/gui/sidebar.py +7 -6
- novelwriter/gui/theme.py +10 -5
- novelwriter/guimain.py +100 -196
- novelwriter/shared.py +66 -27
- novelwriter/text/counting.py +2 -0
- novelwriter/text/patterns.py +168 -60
- novelwriter/tools/manusbuild.py +14 -12
- novelwriter/tools/manuscript.py +120 -78
- novelwriter/tools/manussettings.py +424 -291
- novelwriter/tools/welcome.py +4 -4
- novelwriter/tools/writingstats.py +3 -3
- novelwriter/types.py +23 -7
- novelwriter/core/tohtml.py +0 -530
- novelwriter/core/tomarkdown.py +0 -252
- novelwriter/core/toqdoc.py +0 -419
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
novelwriter/gui/outline.py
CHANGED
@@ -42,14 +42,14 @@ from PyQt5.QtWidgets import (
|
|
42
42
|
|
43
43
|
from novelwriter import CONFIG, SHARED
|
44
44
|
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
45
|
-
from novelwriter.constants import
|
46
|
-
from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
45
|
+
from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst
|
46
|
+
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
47
47
|
from novelwriter.error import logException
|
48
48
|
from novelwriter.extensions.configlayout import NColourLabel
|
49
49
|
from novelwriter.extensions.novelselector import NovelSelector
|
50
50
|
from novelwriter.types import (
|
51
51
|
QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration,
|
52
|
-
QtSizeExpanding, QtUserRole
|
52
|
+
QtScrollAlwaysOff, QtScrollAsNeeded, QtSizeExpanding, QtUserRole
|
53
53
|
)
|
54
54
|
|
55
55
|
logger = logging.getLogger(__name__)
|
@@ -135,11 +135,15 @@ class GuiOutlineView(QWidget):
|
|
135
135
|
self.outlineBar.populateNovelList()
|
136
136
|
self.outlineBar.setCurrentRoot(lastOutline)
|
137
137
|
self.outlineBar.setEnabled(True)
|
138
|
+
self.outlineData.loadGuiSettings()
|
138
139
|
|
139
140
|
return
|
140
141
|
|
141
142
|
def closeProjectTasks(self) -> None:
|
142
143
|
"""Run closing project tasks."""
|
144
|
+
if self.outlineTree.wasRendered:
|
145
|
+
# If the panel hasn't been drawn yet, those values are incorrect
|
146
|
+
self.outlineData.saveGuiSettings()
|
143
147
|
self.outlineTree.closeProjectTasks()
|
144
148
|
self.outlineData.updateClasses()
|
145
149
|
self.clearOutline()
|
@@ -161,8 +165,8 @@ class GuiOutlineView(QWidget):
|
|
161
165
|
# Public Slots
|
162
166
|
##
|
163
167
|
|
164
|
-
@pyqtSlot(str)
|
165
|
-
def updateRootItem(self, tHandle: str) -> None:
|
168
|
+
@pyqtSlot(str, Enum)
|
169
|
+
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
166
170
|
"""Handle tasks whenever a root folders changes."""
|
167
171
|
self.outlineBar.populateNovelList()
|
168
172
|
self.outlineData.updateClasses()
|
@@ -312,43 +316,49 @@ class GuiOutlineToolBar(QToolBar):
|
|
312
316
|
class GuiOutlineTree(QTreeWidget):
|
313
317
|
|
314
318
|
DEF_WIDTH = {
|
315
|
-
nwOutline.TITLE:
|
316
|
-
nwOutline.LEVEL:
|
317
|
-
nwOutline.LABEL:
|
318
|
-
nwOutline.LINE:
|
319
|
-
nwOutline.
|
320
|
-
nwOutline.
|
321
|
-
nwOutline.
|
322
|
-
nwOutline.
|
323
|
-
nwOutline.
|
324
|
-
nwOutline.
|
325
|
-
nwOutline.
|
326
|
-
nwOutline.
|
327
|
-
nwOutline.
|
328
|
-
nwOutline.
|
329
|
-
nwOutline.
|
330
|
-
nwOutline.
|
331
|
-
nwOutline.
|
319
|
+
nwOutline.TITLE: 200,
|
320
|
+
nwOutline.LEVEL: 40,
|
321
|
+
nwOutline.LABEL: 150,
|
322
|
+
nwOutline.LINE: 40,
|
323
|
+
nwOutline.STATUS: 100,
|
324
|
+
nwOutline.CCOUNT: 50,
|
325
|
+
nwOutline.WCOUNT: 50,
|
326
|
+
nwOutline.PCOUNT: 50,
|
327
|
+
nwOutline.POV: 100,
|
328
|
+
nwOutline.FOCUS: 100,
|
329
|
+
nwOutline.CHAR: 100,
|
330
|
+
nwOutline.PLOT: 100,
|
331
|
+
nwOutline.TIME: 100,
|
332
|
+
nwOutline.WORLD: 100,
|
333
|
+
nwOutline.OBJECT: 100,
|
334
|
+
nwOutline.ENTITY: 100,
|
335
|
+
nwOutline.CUSTOM: 100,
|
336
|
+
nwOutline.STORY: 100,
|
337
|
+
nwOutline.MENTION: 100,
|
338
|
+
nwOutline.SYNOP: 200,
|
332
339
|
}
|
333
340
|
|
334
341
|
DEF_HIDDEN = {
|
335
|
-
nwOutline.TITLE:
|
336
|
-
nwOutline.LEVEL:
|
337
|
-
nwOutline.LABEL:
|
338
|
-
nwOutline.LINE:
|
339
|
-
nwOutline.
|
340
|
-
nwOutline.
|
341
|
-
nwOutline.
|
342
|
-
nwOutline.
|
343
|
-
nwOutline.
|
344
|
-
nwOutline.
|
345
|
-
nwOutline.
|
346
|
-
nwOutline.
|
347
|
-
nwOutline.
|
348
|
-
nwOutline.
|
349
|
-
nwOutline.
|
350
|
-
nwOutline.
|
351
|
-
nwOutline.
|
342
|
+
nwOutline.TITLE: False,
|
343
|
+
nwOutline.LEVEL: True,
|
344
|
+
nwOutline.LABEL: False,
|
345
|
+
nwOutline.LINE: True,
|
346
|
+
nwOutline.STATUS: True,
|
347
|
+
nwOutline.CCOUNT: True,
|
348
|
+
nwOutline.WCOUNT: False,
|
349
|
+
nwOutline.PCOUNT: False,
|
350
|
+
nwOutline.POV: False,
|
351
|
+
nwOutline.FOCUS: True,
|
352
|
+
nwOutline.CHAR: False,
|
353
|
+
nwOutline.PLOT: False,
|
354
|
+
nwOutline.TIME: True,
|
355
|
+
nwOutline.WORLD: False,
|
356
|
+
nwOutline.OBJECT: True,
|
357
|
+
nwOutline.ENTITY: True,
|
358
|
+
nwOutline.CUSTOM: True,
|
359
|
+
nwOutline.STORY: True,
|
360
|
+
nwOutline.MENTION: True,
|
361
|
+
nwOutline.SYNOP: False,
|
352
362
|
}
|
353
363
|
|
354
364
|
D_HANDLE = QtUserRole
|
@@ -370,8 +380,8 @@ class GuiOutlineTree(QTreeWidget):
|
|
370
380
|
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
371
381
|
self.setExpandsOnDoubleClick(False)
|
372
382
|
self.setDragEnabled(False)
|
373
|
-
self.itemDoubleClicked.connect(self.
|
374
|
-
self.itemSelectionChanged.connect(self.
|
383
|
+
self.itemDoubleClicked.connect(self._onItemDoubleClicked)
|
384
|
+
self.itemSelectionChanged.connect(self._onItemSelectionChanged)
|
375
385
|
|
376
386
|
self.setIconSize(SHARED.theme.baseIconSize)
|
377
387
|
self.setIndentation(0)
|
@@ -426,6 +436,11 @@ class GuiOutlineTree(QTreeWidget):
|
|
426
436
|
def hiddenColumns(self) -> dict[nwOutline, bool]:
|
427
437
|
return self._colHidden
|
428
438
|
|
439
|
+
@property
|
440
|
+
def wasRendered(self) -> bool:
|
441
|
+
"""Returns True after the Outline has been rendered once."""
|
442
|
+
return not self._firstView
|
443
|
+
|
429
444
|
##
|
430
445
|
# Methods
|
431
446
|
##
|
@@ -433,13 +448,13 @@ class GuiOutlineTree(QTreeWidget):
|
|
433
448
|
def initSettings(self) -> None:
|
434
449
|
"""Set or update outline settings."""
|
435
450
|
if CONFIG.hideVScroll:
|
436
|
-
self.setVerticalScrollBarPolicy(
|
451
|
+
self.setVerticalScrollBarPolicy(QtScrollAlwaysOff)
|
437
452
|
else:
|
438
|
-
self.setVerticalScrollBarPolicy(
|
453
|
+
self.setVerticalScrollBarPolicy(QtScrollAsNeeded)
|
439
454
|
if CONFIG.hideHScroll:
|
440
|
-
self.setHorizontalScrollBarPolicy(
|
455
|
+
self.setHorizontalScrollBarPolicy(QtScrollAlwaysOff)
|
441
456
|
else:
|
442
|
-
self.setHorizontalScrollBarPolicy(
|
457
|
+
self.setHorizontalScrollBarPolicy(QtScrollAsNeeded)
|
443
458
|
return
|
444
459
|
|
445
460
|
def clearContent(self) -> None:
|
@@ -465,8 +480,10 @@ class GuiOutlineTree(QTreeWidget):
|
|
465
480
|
|
466
481
|
return
|
467
482
|
|
468
|
-
def refreshTree(
|
469
|
-
|
483
|
+
def refreshTree(
|
484
|
+
self, rootHandle: str | None = None,
|
485
|
+
overRide: bool = False, novelChanged: bool = False
|
486
|
+
) -> None:
|
470
487
|
"""Called whenever the Outline tab is activated and controls
|
471
488
|
what data to load, and if necessary, force a rebuild of the
|
472
489
|
tree.
|
@@ -546,7 +563,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
546
563
|
##
|
547
564
|
|
548
565
|
@pyqtSlot("QTreeWidgetItem*", int)
|
549
|
-
def
|
566
|
+
def _onItemDoubleClicked(self, tItem: QTreeWidgetItem, tCol: int) -> None:
|
550
567
|
"""Extract the handle and line number of the title double-
|
551
568
|
clicked, and send it to the main gui class for opening in the
|
552
569
|
document editor.
|
@@ -557,14 +574,13 @@ class GuiOutlineTree(QTreeWidget):
|
|
557
574
|
return
|
558
575
|
|
559
576
|
@pyqtSlot()
|
560
|
-
def
|
577
|
+
def _onItemSelectionChanged(self) -> None:
|
561
578
|
"""Extract the handle and line number of the currently selected
|
562
579
|
title, and send it to the details panel.
|
563
580
|
"""
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
sTitle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
581
|
+
if items := self.selectedItems():
|
582
|
+
tHandle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
|
583
|
+
sTitle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
568
584
|
self.activeItemChanged.emit(tHandle, sTitle)
|
569
585
|
return
|
570
586
|
|
@@ -653,6 +669,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
653
669
|
is fast and doesn't require a rebuild of the tree.
|
654
670
|
"""
|
655
671
|
logger.debug("Rebuilding Outline tree")
|
672
|
+
tStart = time()
|
656
673
|
self.clear()
|
657
674
|
|
658
675
|
if self._firstView:
|
@@ -681,45 +698,51 @@ class GuiOutlineTree(QTreeWidget):
|
|
681
698
|
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, activeOnly=True)
|
682
699
|
for _, tHandle, sTitle, novIdx in novStruct:
|
683
700
|
|
684
|
-
iLevel =
|
701
|
+
iLevel = nwStyles.H_LEVEL.get(novIdx.level, 0)
|
685
702
|
nwItem = SHARED.project.tree[tHandle]
|
686
703
|
if iLevel == 0 or nwItem is None:
|
687
704
|
continue
|
705
|
+
sLabel, sIcon = nwItem.getImportStatus()
|
688
706
|
|
689
|
-
|
707
|
+
item = QTreeWidgetItem()
|
690
708
|
hDec = SHARED.theme.getHeaderDecoration(iLevel)
|
691
709
|
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
710
|
+
item.setData(self._colIdx[nwOutline.TITLE], QtDecoration, hDec)
|
711
|
+
item.setText(self._colIdx[nwOutline.TITLE], novIdx.title)
|
712
|
+
item.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle)
|
713
|
+
item.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle)
|
714
|
+
item.setFont(self._colIdx[nwOutline.TITLE], self._hFonts[iLevel])
|
715
|
+
item.setText(self._colIdx[nwOutline.LEVEL], novIdx.level)
|
716
|
+
item.setIcon(self._colIdx[nwOutline.LABEL], self._dIcon[nwItem.mainHeading])
|
717
|
+
item.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName)
|
718
|
+
item.setText(self._colIdx[nwOutline.LINE], f"{novIdx.line:n}")
|
719
|
+
item.setText(self._colIdx[nwOutline.STATUS], sLabel)
|
720
|
+
item.setIcon(self._colIdx[nwOutline.STATUS], sIcon)
|
721
|
+
item.setText(self._colIdx[nwOutline.SYNOP], novIdx.synopsis)
|
722
|
+
item.setText(self._colIdx[nwOutline.CCOUNT], f"{novIdx.charCount:n}")
|
723
|
+
item.setText(self._colIdx[nwOutline.WCOUNT], f"{novIdx.wordCount:n}")
|
724
|
+
item.setText(self._colIdx[nwOutline.PCOUNT], f"{novIdx.paraCount:n}")
|
725
|
+
item.setTextAlignment(self._colIdx[nwOutline.CCOUNT], QtAlignRight)
|
726
|
+
item.setTextAlignment(self._colIdx[nwOutline.WCOUNT], QtAlignRight)
|
727
|
+
item.setTextAlignment(self._colIdx[nwOutline.PCOUNT], QtAlignRight)
|
708
728
|
|
709
729
|
refs = SHARED.project.index.getReferences(tHandle, sTitle)
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
self.
|
730
|
+
item.setText(self._colIdx[nwOutline.POV], ", ".join(refs[nwKeyWords.POV_KEY]))
|
731
|
+
item.setText(self._colIdx[nwOutline.FOCUS], ", ".join(refs[nwKeyWords.FOCUS_KEY]))
|
732
|
+
item.setText(self._colIdx[nwOutline.CHAR], ", ".join(refs[nwKeyWords.CHAR_KEY]))
|
733
|
+
item.setText(self._colIdx[nwOutline.PLOT], ", ".join(refs[nwKeyWords.PLOT_KEY]))
|
734
|
+
item.setText(self._colIdx[nwOutline.TIME], ", ".join(refs[nwKeyWords.TIME_KEY]))
|
735
|
+
item.setText(self._colIdx[nwOutline.WORLD], ", ".join(refs[nwKeyWords.WORLD_KEY]))
|
736
|
+
item.setText(self._colIdx[nwOutline.OBJECT], ", ".join(refs[nwKeyWords.OBJECT_KEY]))
|
737
|
+
item.setText(self._colIdx[nwOutline.ENTITY], ", ".join(refs[nwKeyWords.ENTITY_KEY]))
|
738
|
+
item.setText(self._colIdx[nwOutline.CUSTOM], ", ".join(refs[nwKeyWords.CUSTOM_KEY]))
|
739
|
+
item.setText(self._colIdx[nwOutline.STORY], ", ".join(refs[nwKeyWords.STORY_KEY]))
|
740
|
+
item.setText(self._colIdx[nwOutline.MENTION], ", ".join(refs[nwKeyWords.MENTION_KEY]))
|
741
|
+
|
742
|
+
self.addTopLevelItem(item)
|
721
743
|
|
722
744
|
self._lastBuild = time()
|
745
|
+
logger.debug("Project outline built in %.3f ms", 1000.0*(time() - tStart))
|
723
746
|
|
724
747
|
return
|
725
748
|
|
@@ -793,6 +816,10 @@ class GuiOutlineDetails(QScrollArea):
|
|
793
816
|
|
794
817
|
bFont = SHARED.theme.guiFontB
|
795
818
|
|
819
|
+
trStats1 = trConst(nwLabels.STATS_NAME[nwStats.CHARS_ALL])
|
820
|
+
trStats2 = trConst(nwLabels.STATS_NAME[nwStats.WORDS_ALL])
|
821
|
+
trStats3 = trConst(nwLabels.STATS_NAME[nwStats.PARAGRAPHS])
|
822
|
+
|
796
823
|
# Details Area
|
797
824
|
self.titleLabel = QLabel(self.tr("Title"), self)
|
798
825
|
self.fileLabel = QLabel(self.tr("Document"), self)
|
@@ -813,9 +840,9 @@ class GuiOutlineDetails(QScrollArea):
|
|
813
840
|
self.itemValue.setMaximumWidth(maxTitle)
|
814
841
|
|
815
842
|
# Stats Area
|
816
|
-
self.cCLabel = QLabel(
|
817
|
-
self.wCLabel = QLabel(
|
818
|
-
self.pCLabel = QLabel(
|
843
|
+
self.cCLabel = QLabel(trStats1, self)
|
844
|
+
self.wCLabel = QLabel(trStats2, self)
|
845
|
+
self.pCLabel = QLabel(trStats3, self)
|
819
846
|
self.cCValue = QLabel("", self)
|
820
847
|
self.wCValue = QLabel("", self)
|
821
848
|
self.pCValue = QLabel("", self)
|
@@ -842,96 +869,25 @@ class GuiOutlineDetails(QScrollArea):
|
|
842
869
|
self.synopLWrap = QHBoxLayout()
|
843
870
|
self.synopLWrap.addWidget(self.synopValue, 1)
|
844
871
|
|
845
|
-
# Tags
|
846
|
-
self.povKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]), self)
|
847
|
-
self.focKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]), self)
|
848
|
-
self.chrKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]), self)
|
849
|
-
self.pltKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]), self)
|
850
|
-
self.timKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]), self)
|
851
|
-
self.wldKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]), self)
|
852
|
-
self.objKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]), self)
|
853
|
-
self.entKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]), self)
|
854
|
-
self.cstKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]), self)
|
855
|
-
|
856
|
-
self.povKeyLabel.setFont(bFont)
|
857
|
-
self.focKeyLabel.setFont(bFont)
|
858
|
-
self.chrKeyLabel.setFont(bFont)
|
859
|
-
self.pltKeyLabel.setFont(bFont)
|
860
|
-
self.timKeyLabel.setFont(bFont)
|
861
|
-
self.wldKeyLabel.setFont(bFont)
|
862
|
-
self.objKeyLabel.setFont(bFont)
|
863
|
-
self.entKeyLabel.setFont(bFont)
|
864
|
-
self.cstKeyLabel.setFont(bFont)
|
865
|
-
|
866
|
-
self.povKeyLWrap = QHBoxLayout()
|
867
|
-
self.focKeyLWrap = QHBoxLayout()
|
868
|
-
self.chrKeyLWrap = QHBoxLayout()
|
869
|
-
self.pltKeyLWrap = QHBoxLayout()
|
870
|
-
self.timKeyLWrap = QHBoxLayout()
|
871
|
-
self.wldKeyLWrap = QHBoxLayout()
|
872
|
-
self.objKeyLWrap = QHBoxLayout()
|
873
|
-
self.entKeyLWrap = QHBoxLayout()
|
874
|
-
self.cstKeyLWrap = QHBoxLayout()
|
875
|
-
|
876
|
-
self.povKeyValue = QLabel("", self)
|
877
|
-
self.focKeyValue = QLabel("", self)
|
878
|
-
self.chrKeyValue = QLabel("", self)
|
879
|
-
self.pltKeyValue = QLabel("", self)
|
880
|
-
self.timKeyValue = QLabel("", self)
|
881
|
-
self.wldKeyValue = QLabel("", self)
|
882
|
-
self.objKeyValue = QLabel("", self)
|
883
|
-
self.entKeyValue = QLabel("", self)
|
884
|
-
self.cstKeyValue = QLabel("", self)
|
885
|
-
|
886
|
-
self.povKeyValue.setWordWrap(True)
|
887
|
-
self.focKeyValue.setWordWrap(True)
|
888
|
-
self.chrKeyValue.setWordWrap(True)
|
889
|
-
self.pltKeyValue.setWordWrap(True)
|
890
|
-
self.timKeyValue.setWordWrap(True)
|
891
|
-
self.wldKeyValue.setWordWrap(True)
|
892
|
-
self.objKeyValue.setWordWrap(True)
|
893
|
-
self.entKeyValue.setWordWrap(True)
|
894
|
-
self.cstKeyValue.setWordWrap(True)
|
895
|
-
|
896
|
-
self.povKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
897
|
-
self.focKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
898
|
-
self.chrKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
899
|
-
self.pltKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
900
|
-
self.timKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
901
|
-
self.wldKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
902
|
-
self.objKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
903
|
-
self.entKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
904
|
-
self.cstKeyValue.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
905
|
-
|
906
|
-
self.povKeyLWrap.addWidget(self.povKeyValue, 1)
|
907
|
-
self.focKeyLWrap.addWidget(self.focKeyValue, 1)
|
908
|
-
self.chrKeyLWrap.addWidget(self.chrKeyValue, 1)
|
909
|
-
self.pltKeyLWrap.addWidget(self.pltKeyValue, 1)
|
910
|
-
self.timKeyLWrap.addWidget(self.timKeyValue, 1)
|
911
|
-
self.wldKeyLWrap.addWidget(self.wldKeyValue, 1)
|
912
|
-
self.objKeyLWrap.addWidget(self.objKeyValue, 1)
|
913
|
-
self.entKeyLWrap.addWidget(self.entKeyValue, 1)
|
914
|
-
self.cstKeyLWrap.addWidget(self.cstKeyValue, 1)
|
915
|
-
|
916
872
|
# Selected Item Details
|
917
|
-
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
918
873
|
self.mainForm = QGridLayout()
|
874
|
+
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
919
875
|
self.mainGroup.setLayout(self.mainForm)
|
920
876
|
|
921
|
-
self.mainForm.addWidget(self.titleLabel,
|
922
|
-
self.mainForm.addWidget(self.titleValue,
|
923
|
-
self.mainForm.addWidget(self.cCLabel,
|
924
|
-
self.mainForm.addWidget(self.cCValue,
|
925
|
-
self.mainForm.addWidget(self.fileLabel,
|
926
|
-
self.mainForm.addWidget(self.fileValue,
|
927
|
-
self.mainForm.addWidget(self.wCLabel,
|
928
|
-
self.mainForm.addWidget(self.wCValue,
|
929
|
-
self.mainForm.addWidget(self.itemLabel,
|
930
|
-
self.mainForm.addWidget(self.itemValue,
|
931
|
-
self.mainForm.addWidget(self.pCLabel,
|
932
|
-
self.mainForm.addWidget(self.pCValue,
|
933
|
-
self.mainForm.addWidget(self.synopLabel,
|
934
|
-
self.mainForm.addLayout(self.synopLWrap,
|
877
|
+
self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, QtAlignLeftTop)
|
878
|
+
self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, QtAlignLeftTop)
|
879
|
+
self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, QtAlignLeftTop)
|
880
|
+
self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, QtAlignRightTop)
|
881
|
+
self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, QtAlignLeftTop)
|
882
|
+
self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, QtAlignLeftTop)
|
883
|
+
self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, QtAlignLeftTop)
|
884
|
+
self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, QtAlignRightTop)
|
885
|
+
self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, QtAlignLeftTop)
|
886
|
+
self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, QtAlignLeftTop)
|
887
|
+
self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, QtAlignLeftTop)
|
888
|
+
self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, QtAlignRightTop)
|
889
|
+
self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, QtAlignLeftTop)
|
890
|
+
self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, QtAlignLeftTop)
|
935
891
|
|
936
892
|
self.mainForm.setColumnStretch(1, 1)
|
937
893
|
self.mainForm.setRowStretch(4, 1)
|
@@ -939,45 +895,40 @@ class GuiOutlineDetails(QScrollArea):
|
|
939
895
|
self.mainForm.setVerticalSpacing(vSpace)
|
940
896
|
|
941
897
|
# Selected Item Tags
|
942
|
-
self.tagsGroup = QGroupBox(self.tr("Reference Tags"), self)
|
943
898
|
self.tagsForm = QGridLayout()
|
899
|
+
self.tagsGroup = QGroupBox(self.tr("Reference Tags"), self)
|
944
900
|
self.tagsGroup.setLayout(self.tagsForm)
|
945
901
|
|
946
|
-
self.
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, QtAlignLeftTop)
|
960
|
-
self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, QtAlignLeftTop)
|
961
|
-
self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, QtAlignLeftTop)
|
962
|
-
self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, QtAlignLeftTop)
|
963
|
-
self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, QtAlignLeftTop)
|
902
|
+
self.tagValues: dict[str, tuple[QLabel, QLabel]] = {}
|
903
|
+
for key in nwKeyWords.ALL_KEYS:
|
904
|
+
label = QLabel(trConst(nwLabels.KEY_NAME[key]), self)
|
905
|
+
label.setFont(bFont)
|
906
|
+
value = QLabel("", self)
|
907
|
+
value.setWordWrap(True)
|
908
|
+
value.linkActivated.connect(lambda x: self.itemTagClicked.emit(x))
|
909
|
+
layout = QHBoxLayout()
|
910
|
+
layout.addWidget(value, 1)
|
911
|
+
n = len(self.tagValues)
|
912
|
+
self.tagsForm.addWidget(label, n, 0, QtAlignLeftTop)
|
913
|
+
self.tagsForm.addLayout(layout, n, 1, QtAlignLeftTop)
|
914
|
+
self.tagValues[key] = (label, value)
|
964
915
|
|
965
916
|
self.tagsForm.setColumnStretch(1, 1)
|
966
|
-
self.tagsForm.setRowStretch(
|
917
|
+
self.tagsForm.setRowStretch(len(self.tagValues), 1)
|
967
918
|
self.tagsForm.setHorizontalSpacing(hSpace)
|
968
919
|
self.tagsForm.setVerticalSpacing(vSpace)
|
969
920
|
|
970
921
|
# Assemble
|
971
|
-
self.
|
972
|
-
self.
|
973
|
-
self.
|
974
|
-
self.
|
922
|
+
self.mainSplit = QSplitter(Qt.Orientation.Horizontal)
|
923
|
+
self.mainSplit.addWidget(self.mainGroup)
|
924
|
+
self.mainSplit.addWidget(self.tagsGroup)
|
925
|
+
self.mainSplit.setCollapsible(0, False)
|
926
|
+
self.mainSplit.setCollapsible(1, False)
|
975
927
|
|
976
|
-
self.
|
977
|
-
self.setWidget(self.outerWidget)
|
928
|
+
self.setWidget(self.mainSplit)
|
978
929
|
|
979
|
-
self.setHorizontalScrollBarPolicy(
|
980
|
-
self.setVerticalScrollBarPolicy(
|
930
|
+
self.setHorizontalScrollBarPolicy(QtScrollAsNeeded)
|
931
|
+
self.setVerticalScrollBarPolicy(QtScrollAsNeeded)
|
981
932
|
self.setWidgetResizable(True)
|
982
933
|
self.setFrameStyle(QFrame.Shape.NoFrame)
|
983
934
|
|
@@ -990,35 +941,53 @@ class GuiOutlineDetails(QScrollArea):
|
|
990
941
|
def initSettings(self) -> None:
|
991
942
|
"""Set or update outline settings."""
|
992
943
|
if CONFIG.hideVScroll:
|
993
|
-
self.setVerticalScrollBarPolicy(
|
944
|
+
self.setVerticalScrollBarPolicy(QtScrollAlwaysOff)
|
994
945
|
else:
|
995
|
-
self.setVerticalScrollBarPolicy(
|
946
|
+
self.setVerticalScrollBarPolicy(QtScrollAsNeeded)
|
996
947
|
if CONFIG.hideHScroll:
|
997
|
-
self.setHorizontalScrollBarPolicy(
|
948
|
+
self.setHorizontalScrollBarPolicy(QtScrollAlwaysOff)
|
998
949
|
else:
|
999
|
-
self.setHorizontalScrollBarPolicy(
|
950
|
+
self.setHorizontalScrollBarPolicy(QtScrollAsNeeded)
|
1000
951
|
self.updateClasses()
|
1001
952
|
return
|
1002
953
|
|
954
|
+
def loadGuiSettings(self) -> None:
|
955
|
+
"""Run open project tasks."""
|
956
|
+
parent = self.outlineView.parent() # This widget is rendered already
|
957
|
+
width = parent.width() if isinstance(parent, QWidget) else 1000
|
958
|
+
pOptions = SHARED.project.options
|
959
|
+
self.mainSplit.setSizes([
|
960
|
+
CONFIG.pxInt(pOptions.getInt("GuiOutlineDetails", "detailsWidth", width//3)),
|
961
|
+
CONFIG.pxInt(pOptions.getInt("GuiOutlineDetails", "tagsWidth", 2*width//3))
|
962
|
+
])
|
963
|
+
return
|
964
|
+
|
965
|
+
def saveGuiSettings(self) -> None:
|
966
|
+
"""Run close project tasks."""
|
967
|
+
mainSplit = self.mainSplit.sizes()
|
968
|
+
detailsWidth = CONFIG.rpxInt(mainSplit[0])
|
969
|
+
tagsWidth = CONFIG.rpxInt(mainSplit[1])
|
970
|
+
|
971
|
+
logger.debug("Saving State: GuiOutlineDetails")
|
972
|
+
pOptions = SHARED.project.options
|
973
|
+
pOptions.setValue("GuiOutlineDetails", "detailsWidth", detailsWidth)
|
974
|
+
pOptions.setValue("GuiOutlineDetails", "tagsWidth", tagsWidth)
|
975
|
+
return
|
976
|
+
|
1003
977
|
def clearDetails(self) -> None:
|
1004
978
|
"""Clear all the data labels."""
|
1005
979
|
self.titleLabel.setText(self.tr("Title"))
|
1006
|
-
self.titleValue.
|
1007
|
-
self.fileValue.
|
1008
|
-
self.itemValue.
|
1009
|
-
self.cCValue.
|
1010
|
-
self.wCValue.
|
1011
|
-
self.pCValue.
|
1012
|
-
self.synopValue.
|
1013
|
-
|
1014
|
-
self.
|
1015
|
-
|
1016
|
-
|
1017
|
-
self.timKeyValue.setText("")
|
1018
|
-
self.wldKeyValue.setText("")
|
1019
|
-
self.objKeyValue.setText("")
|
1020
|
-
self.entKeyValue.setText("")
|
1021
|
-
self.cstKeyValue.setText("")
|
980
|
+
self.titleValue.clear()
|
981
|
+
self.fileValue.clear()
|
982
|
+
self.itemValue.clear()
|
983
|
+
self.cCValue.clear()
|
984
|
+
self.wCValue.clear()
|
985
|
+
self.pCValue.clear()
|
986
|
+
self.synopValue.clear()
|
987
|
+
|
988
|
+
for _, value in self.tagValues.values():
|
989
|
+
value.clear()
|
990
|
+
|
1022
991
|
self.updateClasses()
|
1023
992
|
return
|
1024
993
|
|
@@ -1050,15 +1019,8 @@ class GuiOutlineDetails(QScrollArea):
|
|
1050
1019
|
|
1051
1020
|
self.synopValue.setText(novIdx.synopsis)
|
1052
1021
|
|
1053
|
-
self.
|
1054
|
-
|
1055
|
-
self.chrKeyValue.setText(self._formatTags(novRefs, nwKeyWords.CHAR_KEY))
|
1056
|
-
self.pltKeyValue.setText(self._formatTags(novRefs, nwKeyWords.PLOT_KEY))
|
1057
|
-
self.timKeyValue.setText(self._formatTags(novRefs, nwKeyWords.TIME_KEY))
|
1058
|
-
self.wldKeyValue.setText(self._formatTags(novRefs, nwKeyWords.WORLD_KEY))
|
1059
|
-
self.objKeyValue.setText(self._formatTags(novRefs, nwKeyWords.OBJECT_KEY))
|
1060
|
-
self.entKeyValue.setText(self._formatTags(novRefs, nwKeyWords.ENTITY_KEY))
|
1061
|
-
self.cstKeyValue.setText(self._formatTags(novRefs, nwKeyWords.CUSTOM_KEY))
|
1022
|
+
for key, (_, value) in self.tagValues.items():
|
1023
|
+
value.setText(self._formatTags(novRefs, key))
|
1062
1024
|
|
1063
1025
|
return
|
1064
1026
|
|
@@ -1066,27 +1028,12 @@ class GuiOutlineDetails(QScrollArea):
|
|
1066
1028
|
def updateClasses(self) -> None:
|
1067
1029
|
"""Update the visibility status of class details."""
|
1068
1030
|
usedClasses = SHARED.project.tree.rootClasses()
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
cstVisible = nwItemClass.CUSTOM in usedClasses
|
1076
|
-
|
1077
|
-
self.pltKeyLabel.setVisible(pltVisible)
|
1078
|
-
self.pltKeyValue.setVisible(pltVisible)
|
1079
|
-
self.timKeyLabel.setVisible(timVisible)
|
1080
|
-
self.timKeyValue.setVisible(timVisible)
|
1081
|
-
self.wldKeyLabel.setVisible(wldVisible)
|
1082
|
-
self.wldKeyValue.setVisible(wldVisible)
|
1083
|
-
self.objKeyLabel.setVisible(objVisible)
|
1084
|
-
self.objKeyValue.setVisible(objVisible)
|
1085
|
-
self.entKeyLabel.setVisible(entVisible)
|
1086
|
-
self.entKeyValue.setVisible(entVisible)
|
1087
|
-
self.cstKeyLabel.setVisible(cstVisible)
|
1088
|
-
self.cstKeyValue.setVisible(cstVisible)
|
1089
|
-
|
1031
|
+
for key, itemClass in nwKeyWords.KEY_CLASS.items():
|
1032
|
+
visible = itemClass in usedClasses
|
1033
|
+
if key in self.tagValues:
|
1034
|
+
label, value = self.tagValues[key]
|
1035
|
+
label.setVisible(visible)
|
1036
|
+
value.setVisible(visible)
|
1090
1037
|
return
|
1091
1038
|
|
1092
1039
|
@staticmethod
|