Move the outline view into a wrapper widget
This commit is contained in:
@@ -25,7 +25,6 @@ from novelwriter.gui.itemdetails import GuiItemDetails
|
|||||||
from novelwriter.gui.mainmenu import GuiMainMenu
|
from novelwriter.gui.mainmenu import GuiMainMenu
|
||||||
from novelwriter.gui.noveltree import GuiNovelTree
|
from novelwriter.gui.noveltree import GuiNovelTree
|
||||||
from novelwriter.gui.outline import GuiOutline
|
from novelwriter.gui.outline import GuiOutline
|
||||||
from novelwriter.gui.outlinedetails import GuiOutlineDetails
|
|
||||||
from novelwriter.gui.projtree import GuiProjectTree
|
from novelwriter.gui.projtree import GuiProjectTree
|
||||||
from novelwriter.gui.statusbar import GuiMainStatus
|
from novelwriter.gui.statusbar import GuiMainStatus
|
||||||
from novelwriter.gui.theme import GuiTheme
|
from novelwriter.gui.theme import GuiTheme
|
||||||
@@ -40,7 +39,6 @@ __all__ = [
|
|||||||
"GuiMainStatus",
|
"GuiMainStatus",
|
||||||
"GuiNovelTree",
|
"GuiNovelTree",
|
||||||
"GuiOutline",
|
"GuiOutline",
|
||||||
"GuiOutlineDetails",
|
|
||||||
"GuiProjectTree",
|
"GuiProjectTree",
|
||||||
"GuiTheme",
|
"GuiTheme",
|
||||||
"GuiViewsBar",
|
"GuiViewsBar",
|
||||||
|
|||||||
+393
-14
@@ -4,7 +4,9 @@ novelWriter – GUI Project Outline
|
|||||||
GUI class for the project outline view
|
GUI class for the project outline view
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-11-16 [0.4.1]
|
Created: 2019-11-16 [0.4.1] GuiOutlineView, GuiOutlineHeaderMenu
|
||||||
|
Created: 2020-06-02 [0.7.0] GuiOutlineDetails
|
||||||
|
Created: 2022-05-15 [1.7b1] GuiOutline
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
Copyright 2018–2022, Veronica Berglyd Olsen
|
||||||
@@ -28,19 +30,79 @@ import novelwriter
|
|||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot
|
from PyQt5.QtCore import (
|
||||||
|
Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP
|
||||||
|
)
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QTreeWidget, QTreeWidgetItem, QMenu, QAction, QAbstractItemView
|
QAbstractItemView, QAction, QGridLayout, QGroupBox, QHBoxLayout, QLabel,
|
||||||
|
QMenu, QScrollArea, QSplitter, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||||
|
QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter.enum import nwItemLayout, nwItemType, nwOutline
|
from novelwriter.enum import nwItemLayout, nwItemType, nwOutline, nwView
|
||||||
from novelwriter.common import checkInt
|
from novelwriter.common import checkInt
|
||||||
from novelwriter.constants import trConst, nwKeyWords, nwLabels
|
from novelwriter.constants import trConst, nwKeyWords, nwLabels
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GuiOutline(QTreeWidget):
|
class GuiOutline(QWidget):
|
||||||
|
|
||||||
|
viewChangeRequested = pyqtSignal(nwView)
|
||||||
|
|
||||||
|
def __init__(self, theParent):
|
||||||
|
QWidget.__init__(self, theParent)
|
||||||
|
|
||||||
|
self.mainConf = novelwriter.CONFIG
|
||||||
|
self.theParent = theParent
|
||||||
|
self.theProject = theParent.theProject
|
||||||
|
|
||||||
|
self.outlineView = GuiOutlineView(self)
|
||||||
|
self.outlineData = GuiOutlineDetails(self)
|
||||||
|
|
||||||
|
self.splitOutline = QSplitter(Qt.Vertical)
|
||||||
|
self.splitOutline.addWidget(self.outlineView)
|
||||||
|
self.splitOutline.addWidget(self.outlineData)
|
||||||
|
self.splitOutline.setSizes(self.mainConf.getOutlinePanePos())
|
||||||
|
|
||||||
|
# Assemble
|
||||||
|
self.outerBox = QVBoxLayout()
|
||||||
|
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.outerBox.addWidget(self.splitOutline)
|
||||||
|
|
||||||
|
self.setLayout(self.outerBox)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Methods
|
||||||
|
##
|
||||||
|
|
||||||
|
def splitSizes(self):
|
||||||
|
return self.splitOutline.sizes()
|
||||||
|
|
||||||
|
def clearOutline(self):
|
||||||
|
self.outlineData.clearDetails()
|
||||||
|
return
|
||||||
|
|
||||||
|
def initOutline(self):
|
||||||
|
self.outlineView.initOutline()
|
||||||
|
self.outlineData.initDetails()
|
||||||
|
return
|
||||||
|
|
||||||
|
def closeOutline(self):
|
||||||
|
self.outlineView.closeOutline()
|
||||||
|
return
|
||||||
|
|
||||||
|
def refreshView(self, overRide=False, novelChanged=False):
|
||||||
|
self.outlineView.refreshTree(overRide=overRide, novelChanged=novelChanged)
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class GuiOutline
|
||||||
|
|
||||||
|
|
||||||
|
class GuiOutlineView(QTreeWidget):
|
||||||
|
|
||||||
DEF_WIDTH = {
|
DEF_WIDTH = {
|
||||||
nwOutline.TITLE: 200,
|
nwOutline.TITLE: 200,
|
||||||
@@ -82,17 +144,18 @@ class GuiOutline(QTreeWidget):
|
|||||||
nwOutline.SYNOP: False,
|
nwOutline.SYNOP: False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, theParent):
|
def __init__(self, theOutline):
|
||||||
QTreeWidget.__init__(self, theParent)
|
QTreeWidget.__init__(self, theOutline)
|
||||||
|
|
||||||
logger.debug("Initialising GuiOutline ...")
|
logger.debug("Initialising GuiOutline ...")
|
||||||
|
|
||||||
self.mainConf = novelwriter.CONFIG
|
self.mainConf = novelwriter.CONFIG
|
||||||
self.theParent = theParent
|
self.theOutline = theOutline
|
||||||
self.theProject = theParent.theProject
|
self.theParent = theOutline.theParent
|
||||||
self.theTheme = theParent.theTheme
|
self.theProject = theOutline.theParent.theProject
|
||||||
self.theIndex = theParent.theIndex
|
self.theTheme = theOutline.theParent.theTheme
|
||||||
self.optState = theParent.theProject.optState
|
self.theIndex = theOutline.theParent.theIndex
|
||||||
|
self.optState = theOutline.theParent.theProject.optState
|
||||||
self.headerMenu = GuiOutlineHeaderMenu(self)
|
self.headerMenu = GuiOutlineHeaderMenu(self)
|
||||||
|
|
||||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
@@ -233,7 +296,7 @@ class GuiOutline(QTreeWidget):
|
|||||||
if selItems:
|
if selItems:
|
||||||
tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole)
|
tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole)
|
||||||
sTitle = selItems[0].data(self._colIdx[nwOutline.LINE], Qt.UserRole)
|
sTitle = selItems[0].data(self._colIdx[nwOutline.LINE], Qt.UserRole)
|
||||||
self.theParent.projMeta.showItem(tHandle, sTitle)
|
self.theOutline.outlineData.showItem(tHandle, sTitle)
|
||||||
self.theParent.treeView.setSelectedHandle(tHandle)
|
self.theParent.treeView.setSelectedHandle(tHandle)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -477,7 +540,7 @@ class GuiOutline(QTreeWidget):
|
|||||||
|
|
||||||
return newItem
|
return newItem
|
||||||
|
|
||||||
# END Class GuiOutline
|
# END Class GuiOutlineView
|
||||||
|
|
||||||
|
|
||||||
class GuiOutlineHeaderMenu(QMenu):
|
class GuiOutlineHeaderMenu(QMenu):
|
||||||
@@ -533,3 +596,319 @@ class GuiOutlineHeaderMenu(QMenu):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiOutlineHeaderMenu
|
# END Class GuiOutlineHeaderMenu
|
||||||
|
|
||||||
|
|
||||||
|
class GuiOutlineDetails(QScrollArea):
|
||||||
|
|
||||||
|
LVL_MAP = {
|
||||||
|
"H1": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Title"),
|
||||||
|
"H2": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Chapter"),
|
||||||
|
"H3": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Scene"),
|
||||||
|
"H4": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Section"),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, theOutline):
|
||||||
|
QScrollArea.__init__(self, theOutline)
|
||||||
|
|
||||||
|
logger.debug("Initialising GuiOutlineDetails ...")
|
||||||
|
|
||||||
|
self.mainConf = novelwriter.CONFIG
|
||||||
|
self.theOutline = theOutline
|
||||||
|
self.theParent = theOutline.theParent
|
||||||
|
self.theProject = theOutline.theParent.theProject
|
||||||
|
self.theTheme = theOutline.theParent.theTheme
|
||||||
|
self.theIndex = theOutline.theParent.theIndex
|
||||||
|
self.optState = theOutline.theParent.theProject.optState
|
||||||
|
|
||||||
|
# Sizes
|
||||||
|
minTitle = 30*self.theTheme.textNWidth
|
||||||
|
maxTitle = 40*self.theTheme.textNWidth
|
||||||
|
wCount = self.theTheme.getTextWidth("999,999")
|
||||||
|
hSpace = int(self.mainConf.pxInt(10))
|
||||||
|
vSpace = int(self.mainConf.pxInt(4))
|
||||||
|
|
||||||
|
# Details Area
|
||||||
|
self.titleLabel = QLabel("<b>%s</b>" % self.tr("Title"))
|
||||||
|
self.fileLabel = QLabel("<b>%s</b>" % self.tr("Document"))
|
||||||
|
self.itemLabel = QLabel("<b>%s</b>" % self.tr("Status"))
|
||||||
|
self.titleValue = QLabel("")
|
||||||
|
self.fileValue = QLabel("")
|
||||||
|
self.itemValue = QLabel("")
|
||||||
|
|
||||||
|
self.titleValue.setMinimumWidth(minTitle)
|
||||||
|
self.titleValue.setMaximumWidth(maxTitle)
|
||||||
|
self.fileValue.setMinimumWidth(minTitle)
|
||||||
|
self.fileValue.setMaximumWidth(maxTitle)
|
||||||
|
self.itemValue.setMinimumWidth(minTitle)
|
||||||
|
self.itemValue.setMaximumWidth(maxTitle)
|
||||||
|
|
||||||
|
# Stats Area
|
||||||
|
self.cCLabel = QLabel("<b>%s</b>" % self.tr("Characters"))
|
||||||
|
self.wCLabel = QLabel("<b>%s</b>" % self.tr("Words"))
|
||||||
|
self.pCLabel = QLabel("<b>%s</b>" % self.tr("Paragraphs"))
|
||||||
|
self.cCValue = QLabel("")
|
||||||
|
self.wCValue = QLabel("")
|
||||||
|
self.pCValue = QLabel("")
|
||||||
|
|
||||||
|
self.cCValue.setMinimumWidth(wCount)
|
||||||
|
self.wCValue.setMinimumWidth(wCount)
|
||||||
|
self.pCValue.setMinimumWidth(wCount)
|
||||||
|
self.cCValue.setAlignment(Qt.AlignRight)
|
||||||
|
self.wCValue.setAlignment(Qt.AlignRight)
|
||||||
|
self.pCValue.setAlignment(Qt.AlignRight)
|
||||||
|
|
||||||
|
# Synopsis
|
||||||
|
self.synopLabel = QLabel("<b>%s</b>" % self.tr("Synopsis"))
|
||||||
|
self.synopValue = QLabel("")
|
||||||
|
self.synopLWrap = QHBoxLayout()
|
||||||
|
self.synopValue.setWordWrap(True)
|
||||||
|
self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.synopLWrap.addWidget(self.synopValue, 1)
|
||||||
|
|
||||||
|
# Tags
|
||||||
|
self.povKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
|
||||||
|
self.focKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
|
||||||
|
self.chrKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
|
||||||
|
self.pltKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
|
||||||
|
self.timKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
|
||||||
|
self.wldKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
|
||||||
|
self.objKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
|
||||||
|
self.entKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
|
||||||
|
self.cstKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
|
||||||
|
|
||||||
|
self.povKeyLWrap = QHBoxLayout()
|
||||||
|
self.focKeyLWrap = QHBoxLayout()
|
||||||
|
self.chrKeyLWrap = QHBoxLayout()
|
||||||
|
self.pltKeyLWrap = QHBoxLayout()
|
||||||
|
self.timKeyLWrap = QHBoxLayout()
|
||||||
|
self.wldKeyLWrap = QHBoxLayout()
|
||||||
|
self.objKeyLWrap = QHBoxLayout()
|
||||||
|
self.entKeyLWrap = QHBoxLayout()
|
||||||
|
self.cstKeyLWrap = QHBoxLayout()
|
||||||
|
|
||||||
|
self.povKeyValue = QLabel("")
|
||||||
|
self.focKeyValue = QLabel("")
|
||||||
|
self.chrKeyValue = QLabel("")
|
||||||
|
self.pltKeyValue = QLabel("")
|
||||||
|
self.timKeyValue = QLabel("")
|
||||||
|
self.wldKeyValue = QLabel("")
|
||||||
|
self.objKeyValue = QLabel("")
|
||||||
|
self.entKeyValue = QLabel("")
|
||||||
|
self.cstKeyValue = QLabel("")
|
||||||
|
|
||||||
|
self.povKeyValue.setWordWrap(True)
|
||||||
|
self.focKeyValue.setWordWrap(True)
|
||||||
|
self.chrKeyValue.setWordWrap(True)
|
||||||
|
self.pltKeyValue.setWordWrap(True)
|
||||||
|
self.timKeyValue.setWordWrap(True)
|
||||||
|
self.wldKeyValue.setWordWrap(True)
|
||||||
|
self.objKeyValue.setWordWrap(True)
|
||||||
|
self.entKeyValue.setWordWrap(True)
|
||||||
|
self.cstKeyValue.setWordWrap(True)
|
||||||
|
|
||||||
|
self.povKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.focKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.chrKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.pltKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.timKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.wldKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.objKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.entKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
self.cstKeyValue.linkActivated.connect(self._tagClicked)
|
||||||
|
|
||||||
|
self.povKeyLWrap.addWidget(self.povKeyValue, 1)
|
||||||
|
self.focKeyLWrap.addWidget(self.focKeyValue, 1)
|
||||||
|
self.chrKeyLWrap.addWidget(self.chrKeyValue, 1)
|
||||||
|
self.pltKeyLWrap.addWidget(self.pltKeyValue, 1)
|
||||||
|
self.timKeyLWrap.addWidget(self.timKeyValue, 1)
|
||||||
|
self.wldKeyLWrap.addWidget(self.wldKeyValue, 1)
|
||||||
|
self.objKeyLWrap.addWidget(self.objKeyValue, 1)
|
||||||
|
self.entKeyLWrap.addWidget(self.entKeyValue, 1)
|
||||||
|
self.cstKeyLWrap.addWidget(self.cstKeyValue, 1)
|
||||||
|
|
||||||
|
# Selected Item Details
|
||||||
|
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
||||||
|
self.mainForm = QGridLayout()
|
||||||
|
self.mainGroup.setLayout(self.mainForm)
|
||||||
|
|
||||||
|
self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
||||||
|
self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
||||||
|
self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
||||||
|
self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
|
||||||
|
self.mainForm.setColumnStretch(1, 1)
|
||||||
|
self.mainForm.setRowStretch(4, 1)
|
||||||
|
self.mainForm.setHorizontalSpacing(hSpace)
|
||||||
|
self.mainForm.setVerticalSpacing(vSpace)
|
||||||
|
|
||||||
|
# Selected Item Tags
|
||||||
|
self.tagsGroup = QGroupBox(self.tr("Reference Tags"), self)
|
||||||
|
self.tagsForm = QGridLayout()
|
||||||
|
self.tagsGroup.setLayout(self.tagsForm)
|
||||||
|
|
||||||
|
self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
|
||||||
|
self.tagsForm.setColumnStretch(1, 1)
|
||||||
|
self.tagsForm.setRowStretch(8, 1)
|
||||||
|
self.tagsForm.setHorizontalSpacing(hSpace)
|
||||||
|
self.tagsForm.setVerticalSpacing(vSpace)
|
||||||
|
|
||||||
|
# Assemble
|
||||||
|
self.outerWidget = QWidget()
|
||||||
|
self.outerBox = QHBoxLayout()
|
||||||
|
self.outerBox.addWidget(self.mainGroup, 0)
|
||||||
|
self.outerBox.addWidget(self.tagsGroup, 1)
|
||||||
|
|
||||||
|
self.outerWidget.setLayout(self.outerBox)
|
||||||
|
self.setWidget(self.outerWidget)
|
||||||
|
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||||
|
self.setWidgetResizable(True)
|
||||||
|
|
||||||
|
self.initDetails()
|
||||||
|
|
||||||
|
logger.debug("GuiOutlineDetails initialisation complete")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def initDetails(self):
|
||||||
|
"""Set or update outline settings.
|
||||||
|
"""
|
||||||
|
# Scroll bars
|
||||||
|
if self.mainConf.hideVScroll:
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
else:
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||||
|
|
||||||
|
if self.mainConf.hideHScroll:
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
else:
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def clearDetails(self):
|
||||||
|
"""Clear all the data labels.
|
||||||
|
"""
|
||||||
|
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
||||||
|
self.titleValue.setText("")
|
||||||
|
self.fileValue.setText("")
|
||||||
|
self.itemValue.setText("")
|
||||||
|
self.cCValue.setText("")
|
||||||
|
self.wCValue.setText("")
|
||||||
|
self.pCValue.setText("")
|
||||||
|
self.synopValue.setText("")
|
||||||
|
self.povKeyValue.setText("")
|
||||||
|
self.focKeyValue.setText("")
|
||||||
|
self.chrKeyValue.setText("")
|
||||||
|
self.pltKeyValue.setText("")
|
||||||
|
self.timKeyValue.setText("")
|
||||||
|
self.wldKeyValue.setText("")
|
||||||
|
self.objKeyValue.setText("")
|
||||||
|
self.entKeyValue.setText("")
|
||||||
|
self.cstKeyValue.setText("")
|
||||||
|
return
|
||||||
|
|
||||||
|
def showItem(self, tHandle, sTitle):
|
||||||
|
"""Update the content of the tree with the given handle and line
|
||||||
|
number pointing to a header.
|
||||||
|
"""
|
||||||
|
nwItem = self.theProject.projTree[tHandle]
|
||||||
|
novIdx = self.theIndex.getNovelData(tHandle, sTitle)
|
||||||
|
theRefs = self.theIndex.getReferences(tHandle, sTitle)
|
||||||
|
if nwItem is None or novIdx is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if novIdx["level"] in self.LVL_MAP:
|
||||||
|
self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP[novIdx["level"]]))
|
||||||
|
else:
|
||||||
|
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
||||||
|
self.titleValue.setText(novIdx["title"])
|
||||||
|
|
||||||
|
itemStatus, _ = nwItem.getImportStatus()
|
||||||
|
|
||||||
|
self.fileValue.setText(nwItem.itemName)
|
||||||
|
self.itemValue.setText(itemStatus)
|
||||||
|
|
||||||
|
cC = checkInt(novIdx["cCount"], 0)
|
||||||
|
wC = checkInt(novIdx["wCount"], 0)
|
||||||
|
pC = checkInt(novIdx["pCount"], 0)
|
||||||
|
|
||||||
|
self.cCValue.setText(f"{cC:n}")
|
||||||
|
self.wCValue.setText(f"{wC:n}")
|
||||||
|
self.pCValue.setText(f"{pC:n}")
|
||||||
|
|
||||||
|
self.synopValue.setText(novIdx["synopsis"])
|
||||||
|
|
||||||
|
self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_KEY))
|
||||||
|
self.focKeyValue.setText(self._formatTags(theRefs, nwKeyWords.FOCUS_KEY))
|
||||||
|
self.chrKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CHAR_KEY))
|
||||||
|
self.pltKeyValue.setText(self._formatTags(theRefs, nwKeyWords.PLOT_KEY))
|
||||||
|
self.timKeyValue.setText(self._formatTags(theRefs, nwKeyWords.TIME_KEY))
|
||||||
|
self.wldKeyValue.setText(self._formatTags(theRefs, nwKeyWords.WORLD_KEY))
|
||||||
|
self.objKeyValue.setText(self._formatTags(theRefs, nwKeyWords.OBJECT_KEY))
|
||||||
|
self.entKeyValue.setText(self._formatTags(theRefs, nwKeyWords.ENTITY_KEY))
|
||||||
|
self.cstKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CUSTOM_KEY))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Slots
|
||||||
|
##
|
||||||
|
|
||||||
|
def _tagClicked(self, theLink):
|
||||||
|
"""Capture the click of a tag in the right-most column.
|
||||||
|
"""
|
||||||
|
logger.verbose("Clicked link: '%s'", theLink)
|
||||||
|
if len(theLink) > 0:
|
||||||
|
theBits = theLink.split("=")
|
||||||
|
if len(theBits) == 2:
|
||||||
|
self.theOutline.viewChangeRequested.emit(nwView.PROJECT)
|
||||||
|
self.theParent.docViewer.loadFromTag(theBits[1])
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _formatTags(self, theRefs, theKey):
|
||||||
|
"""Format the tags as clickable links.
|
||||||
|
"""
|
||||||
|
if theKey not in theRefs:
|
||||||
|
return ""
|
||||||
|
refTags = []
|
||||||
|
for tTag in theRefs[theKey]:
|
||||||
|
refTags.append("<a href='#%s=%s'>%s</a>" % (
|
||||||
|
theKey[1:], tTag, tTag
|
||||||
|
))
|
||||||
|
return ", ".join(refTags)
|
||||||
|
|
||||||
|
# END Class GuiOutlineDetails
|
||||||
|
|||||||
@@ -1,355 +0,0 @@
|
|||||||
"""
|
|
||||||
novelWriter – GUI Project Outline Details
|
|
||||||
=========================================
|
|
||||||
GUI class for the project outline details panel
|
|
||||||
|
|
||||||
File History:
|
|
||||||
Created: 2020-06-02 [0.7.0]
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import novelwriter
|
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QT_TRANSLATE_NOOP, pyqtSignal
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QScrollArea, QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel
|
|
||||||
)
|
|
||||||
|
|
||||||
from novelwriter.enum import nwView
|
|
||||||
from novelwriter.common import checkInt
|
|
||||||
from novelwriter.constants import trConst, nwKeyWords, nwLabels
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class GuiOutlineDetails(QScrollArea):
|
|
||||||
|
|
||||||
LVL_MAP = {
|
|
||||||
"H1": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Title"),
|
|
||||||
"H2": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Chapter"),
|
|
||||||
"H3": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Scene"),
|
|
||||||
"H4": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Section"),
|
|
||||||
}
|
|
||||||
|
|
||||||
viewChangeRequested = pyqtSignal(nwView)
|
|
||||||
|
|
||||||
def __init__(self, theParent):
|
|
||||||
QScrollArea.__init__(self, theParent)
|
|
||||||
|
|
||||||
logger.debug("Initialising GuiOutlineDetails ...")
|
|
||||||
|
|
||||||
self.mainConf = novelwriter.CONFIG
|
|
||||||
self.theParent = theParent
|
|
||||||
self.theProject = theParent.theProject
|
|
||||||
self.theTheme = theParent.theTheme
|
|
||||||
self.theIndex = theParent.theIndex
|
|
||||||
self.optState = theParent.theProject.optState
|
|
||||||
|
|
||||||
# Sizes
|
|
||||||
minTitle = 30*self.theTheme.textNWidth
|
|
||||||
maxTitle = 40*self.theTheme.textNWidth
|
|
||||||
wCount = self.theTheme.getTextWidth("999,999")
|
|
||||||
hSpace = int(self.mainConf.pxInt(10))
|
|
||||||
vSpace = int(self.mainConf.pxInt(4))
|
|
||||||
|
|
||||||
# Details Area
|
|
||||||
self.titleLabel = QLabel("<b>%s</b>" % self.tr("Title"))
|
|
||||||
self.fileLabel = QLabel("<b>%s</b>" % self.tr("Document"))
|
|
||||||
self.itemLabel = QLabel("<b>%s</b>" % self.tr("Status"))
|
|
||||||
self.titleValue = QLabel("")
|
|
||||||
self.fileValue = QLabel("")
|
|
||||||
self.itemValue = QLabel("")
|
|
||||||
|
|
||||||
self.titleValue.setMinimumWidth(minTitle)
|
|
||||||
self.titleValue.setMaximumWidth(maxTitle)
|
|
||||||
self.fileValue.setMinimumWidth(minTitle)
|
|
||||||
self.fileValue.setMaximumWidth(maxTitle)
|
|
||||||
self.itemValue.setMinimumWidth(minTitle)
|
|
||||||
self.itemValue.setMaximumWidth(maxTitle)
|
|
||||||
|
|
||||||
# Stats Area
|
|
||||||
self.cCLabel = QLabel("<b>%s</b>" % self.tr("Characters"))
|
|
||||||
self.wCLabel = QLabel("<b>%s</b>" % self.tr("Words"))
|
|
||||||
self.pCLabel = QLabel("<b>%s</b>" % self.tr("Paragraphs"))
|
|
||||||
self.cCValue = QLabel("")
|
|
||||||
self.wCValue = QLabel("")
|
|
||||||
self.pCValue = QLabel("")
|
|
||||||
|
|
||||||
self.cCValue.setMinimumWidth(wCount)
|
|
||||||
self.wCValue.setMinimumWidth(wCount)
|
|
||||||
self.pCValue.setMinimumWidth(wCount)
|
|
||||||
self.cCValue.setAlignment(Qt.AlignRight)
|
|
||||||
self.wCValue.setAlignment(Qt.AlignRight)
|
|
||||||
self.pCValue.setAlignment(Qt.AlignRight)
|
|
||||||
|
|
||||||
# Synopsis
|
|
||||||
self.synopLabel = QLabel("<b>%s</b>" % self.tr("Synopsis"))
|
|
||||||
self.synopValue = QLabel("")
|
|
||||||
self.synopLWrap = QHBoxLayout()
|
|
||||||
self.synopValue.setWordWrap(True)
|
|
||||||
self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.synopLWrap.addWidget(self.synopValue, 1)
|
|
||||||
|
|
||||||
# Tags
|
|
||||||
self.povKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
|
|
||||||
self.focKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
|
|
||||||
self.chrKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
|
|
||||||
self.pltKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
|
|
||||||
self.timKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
|
|
||||||
self.wldKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
|
|
||||||
self.objKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
|
|
||||||
self.entKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
|
|
||||||
self.cstKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
|
|
||||||
|
|
||||||
self.povKeyLWrap = QHBoxLayout()
|
|
||||||
self.focKeyLWrap = QHBoxLayout()
|
|
||||||
self.chrKeyLWrap = QHBoxLayout()
|
|
||||||
self.pltKeyLWrap = QHBoxLayout()
|
|
||||||
self.timKeyLWrap = QHBoxLayout()
|
|
||||||
self.wldKeyLWrap = QHBoxLayout()
|
|
||||||
self.objKeyLWrap = QHBoxLayout()
|
|
||||||
self.entKeyLWrap = QHBoxLayout()
|
|
||||||
self.cstKeyLWrap = QHBoxLayout()
|
|
||||||
|
|
||||||
self.povKeyValue = QLabel("")
|
|
||||||
self.focKeyValue = QLabel("")
|
|
||||||
self.chrKeyValue = QLabel("")
|
|
||||||
self.pltKeyValue = QLabel("")
|
|
||||||
self.timKeyValue = QLabel("")
|
|
||||||
self.wldKeyValue = QLabel("")
|
|
||||||
self.objKeyValue = QLabel("")
|
|
||||||
self.entKeyValue = QLabel("")
|
|
||||||
self.cstKeyValue = QLabel("")
|
|
||||||
|
|
||||||
self.povKeyValue.setWordWrap(True)
|
|
||||||
self.focKeyValue.setWordWrap(True)
|
|
||||||
self.chrKeyValue.setWordWrap(True)
|
|
||||||
self.pltKeyValue.setWordWrap(True)
|
|
||||||
self.timKeyValue.setWordWrap(True)
|
|
||||||
self.wldKeyValue.setWordWrap(True)
|
|
||||||
self.objKeyValue.setWordWrap(True)
|
|
||||||
self.entKeyValue.setWordWrap(True)
|
|
||||||
self.cstKeyValue.setWordWrap(True)
|
|
||||||
|
|
||||||
self.povKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.focKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.chrKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.pltKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.timKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.wldKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.objKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.entKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
self.cstKeyValue.linkActivated.connect(self._tagClicked)
|
|
||||||
|
|
||||||
self.povKeyLWrap.addWidget(self.povKeyValue, 1)
|
|
||||||
self.focKeyLWrap.addWidget(self.focKeyValue, 1)
|
|
||||||
self.chrKeyLWrap.addWidget(self.chrKeyValue, 1)
|
|
||||||
self.pltKeyLWrap.addWidget(self.pltKeyValue, 1)
|
|
||||||
self.timKeyLWrap.addWidget(self.timKeyValue, 1)
|
|
||||||
self.wldKeyLWrap.addWidget(self.wldKeyValue, 1)
|
|
||||||
self.objKeyLWrap.addWidget(self.objKeyValue, 1)
|
|
||||||
self.entKeyLWrap.addWidget(self.entKeyValue, 1)
|
|
||||||
self.cstKeyLWrap.addWidget(self.cstKeyValue, 1)
|
|
||||||
|
|
||||||
# Selected Item Details
|
|
||||||
self.mainGroup = QGroupBox(self.tr("Title Details"), self)
|
|
||||||
self.mainForm = QGridLayout()
|
|
||||||
self.mainGroup.setLayout(self.mainForm)
|
|
||||||
|
|
||||||
self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
|
||||||
self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
|
||||||
self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, Qt.AlignTop | Qt.AlignRight)
|
|
||||||
self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
|
|
||||||
self.mainForm.setColumnStretch(1, 1)
|
|
||||||
self.mainForm.setRowStretch(4, 1)
|
|
||||||
self.mainForm.setHorizontalSpacing(hSpace)
|
|
||||||
self.mainForm.setVerticalSpacing(vSpace)
|
|
||||||
|
|
||||||
# Selected Item Tags
|
|
||||||
self.tagsGroup = QGroupBox(self.tr("Reference Tags"), self)
|
|
||||||
self.tagsForm = QGridLayout()
|
|
||||||
self.tagsGroup.setLayout(self.tagsForm)
|
|
||||||
|
|
||||||
self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
|
|
||||||
|
|
||||||
self.tagsForm.setColumnStretch(1, 1)
|
|
||||||
self.tagsForm.setRowStretch(8, 1)
|
|
||||||
self.tagsForm.setHorizontalSpacing(hSpace)
|
|
||||||
self.tagsForm.setVerticalSpacing(vSpace)
|
|
||||||
|
|
||||||
# Assemble
|
|
||||||
self.outerWidget = QWidget()
|
|
||||||
self.outerBox = QHBoxLayout()
|
|
||||||
self.outerBox.addWidget(self.mainGroup, 0)
|
|
||||||
self.outerBox.addWidget(self.tagsGroup, 1)
|
|
||||||
|
|
||||||
self.outerWidget.setLayout(self.outerBox)
|
|
||||||
self.setWidget(self.outerWidget)
|
|
||||||
|
|
||||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
|
||||||
self.setWidgetResizable(True)
|
|
||||||
|
|
||||||
self.initDetails()
|
|
||||||
|
|
||||||
logger.debug("GuiOutlineDetails initialisation complete")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def initDetails(self):
|
|
||||||
"""Set or update outline settings.
|
|
||||||
"""
|
|
||||||
# Scroll bars
|
|
||||||
if self.mainConf.hideVScroll:
|
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
||||||
else:
|
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
|
||||||
|
|
||||||
if self.mainConf.hideHScroll:
|
|
||||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
||||||
else:
|
|
||||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def clearDetails(self):
|
|
||||||
"""Clear all the data labels.
|
|
||||||
"""
|
|
||||||
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
|
||||||
self.titleValue.setText("")
|
|
||||||
self.fileValue.setText("")
|
|
||||||
self.itemValue.setText("")
|
|
||||||
self.cCValue.setText("")
|
|
||||||
self.wCValue.setText("")
|
|
||||||
self.pCValue.setText("")
|
|
||||||
self.synopValue.setText("")
|
|
||||||
self.povKeyValue.setText("")
|
|
||||||
self.focKeyValue.setText("")
|
|
||||||
self.chrKeyValue.setText("")
|
|
||||||
self.pltKeyValue.setText("")
|
|
||||||
self.timKeyValue.setText("")
|
|
||||||
self.wldKeyValue.setText("")
|
|
||||||
self.objKeyValue.setText("")
|
|
||||||
self.entKeyValue.setText("")
|
|
||||||
self.cstKeyValue.setText("")
|
|
||||||
return
|
|
||||||
|
|
||||||
def showItem(self, tHandle, sTitle):
|
|
||||||
"""Update the content of the tree with the given handle and line
|
|
||||||
number pointing to a header.
|
|
||||||
"""
|
|
||||||
nwItem = self.theProject.projTree[tHandle]
|
|
||||||
novIdx = self.theIndex.getNovelData(tHandle, sTitle)
|
|
||||||
theRefs = self.theIndex.getReferences(tHandle, sTitle)
|
|
||||||
if nwItem is None or novIdx is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if novIdx["level"] in self.LVL_MAP:
|
|
||||||
self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP[novIdx["level"]]))
|
|
||||||
else:
|
|
||||||
self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
|
|
||||||
self.titleValue.setText(novIdx["title"])
|
|
||||||
|
|
||||||
itemStatus, _ = nwItem.getImportStatus()
|
|
||||||
|
|
||||||
self.fileValue.setText(nwItem.itemName)
|
|
||||||
self.itemValue.setText(itemStatus)
|
|
||||||
|
|
||||||
cC = checkInt(novIdx["cCount"], 0)
|
|
||||||
wC = checkInt(novIdx["wCount"], 0)
|
|
||||||
pC = checkInt(novIdx["pCount"], 0)
|
|
||||||
|
|
||||||
self.cCValue.setText(f"{cC:n}")
|
|
||||||
self.wCValue.setText(f"{wC:n}")
|
|
||||||
self.pCValue.setText(f"{pC:n}")
|
|
||||||
|
|
||||||
self.synopValue.setText(novIdx["synopsis"])
|
|
||||||
|
|
||||||
self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_KEY))
|
|
||||||
self.focKeyValue.setText(self._formatTags(theRefs, nwKeyWords.FOCUS_KEY))
|
|
||||||
self.chrKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CHAR_KEY))
|
|
||||||
self.pltKeyValue.setText(self._formatTags(theRefs, nwKeyWords.PLOT_KEY))
|
|
||||||
self.timKeyValue.setText(self._formatTags(theRefs, nwKeyWords.TIME_KEY))
|
|
||||||
self.wldKeyValue.setText(self._formatTags(theRefs, nwKeyWords.WORLD_KEY))
|
|
||||||
self.objKeyValue.setText(self._formatTags(theRefs, nwKeyWords.OBJECT_KEY))
|
|
||||||
self.entKeyValue.setText(self._formatTags(theRefs, nwKeyWords.ENTITY_KEY))
|
|
||||||
self.cstKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CUSTOM_KEY))
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
##
|
|
||||||
# Slots
|
|
||||||
##
|
|
||||||
|
|
||||||
def _tagClicked(self, theLink):
|
|
||||||
"""Capture the click of a tag in the right-most column.
|
|
||||||
"""
|
|
||||||
logger.verbose("Clicked link: '%s'", theLink)
|
|
||||||
if len(theLink) > 0:
|
|
||||||
theBits = theLink.split("=")
|
|
||||||
if len(theBits) == 2:
|
|
||||||
self.viewChangeRequested.emit(nwView.PROJECT)
|
|
||||||
self.theParent.docViewer.loadFromTag(theBits[1])
|
|
||||||
return
|
|
||||||
|
|
||||||
##
|
|
||||||
# Internal Functions
|
|
||||||
##
|
|
||||||
|
|
||||||
def _formatTags(self, theRefs, theKey):
|
|
||||||
"""Format the tags as clickable links.
|
|
||||||
"""
|
|
||||||
if theKey not in theRefs:
|
|
||||||
return ""
|
|
||||||
refTags = []
|
|
||||||
for tTag in theRefs[theKey]:
|
|
||||||
refTags.append("<a href='#%s=%s'>%s</a>" % (
|
|
||||||
theKey[1:], tTag, tTag
|
|
||||||
))
|
|
||||||
return ", ".join(refTags)
|
|
||||||
|
|
||||||
# END Class GuiOutlineDetails
|
|
||||||
+11
-19
@@ -39,8 +39,8 @@ from PyQt5.QtWidgets import (
|
|||||||
|
|
||||||
from novelwriter.gui import (
|
from novelwriter.gui import (
|
||||||
GuiDocEditor, GuiDocViewDetails, GuiDocViewer, GuiItemDetails, GuiMainMenu,
|
GuiDocEditor, GuiDocViewDetails, GuiDocViewer, GuiItemDetails, GuiMainMenu,
|
||||||
GuiMainStatus, GuiNovelTree, GuiOutline, GuiOutlineDetails, GuiProjectTree,
|
GuiMainStatus, GuiNovelTree, GuiOutline, GuiProjectTree, GuiTheme,
|
||||||
GuiTheme, GuiViewsBar
|
GuiViewsBar
|
||||||
)
|
)
|
||||||
from novelwriter.dialogs import (
|
from novelwriter.dialogs import (
|
||||||
GuiAbout, GuiDocMerge, GuiDocSplit, GuiItemEditor, GuiPreferences,
|
GuiAbout, GuiDocMerge, GuiDocSplit, GuiItemEditor, GuiPreferences,
|
||||||
@@ -112,7 +112,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.docViewer = GuiDocViewer(self)
|
self.docViewer = GuiDocViewer(self)
|
||||||
self.treeMeta = GuiItemDetails(self)
|
self.treeMeta = GuiItemDetails(self)
|
||||||
self.projView = GuiOutline(self)
|
self.projView = GuiOutline(self)
|
||||||
self.projMeta = GuiOutlineDetails(self)
|
|
||||||
self.mainMenu = GuiMainMenu(self)
|
self.mainMenu = GuiMainMenu(self)
|
||||||
self.viewsBar = GuiViewsBar(self)
|
self.viewsBar = GuiViewsBar(self)
|
||||||
|
|
||||||
@@ -128,7 +127,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
||||||
|
|
||||||
self.viewsBar.viewChangeRequested.connect(self._changeView)
|
self.viewsBar.viewChangeRequested.connect(self._changeView)
|
||||||
self.projMeta.viewChangeRequested.connect(self._changeView)
|
self.projView.viewChangeRequested.connect(self._changeView)
|
||||||
|
|
||||||
# Project Tree Stack
|
# Project Tree Stack
|
||||||
self.projStack = QStackedWidget()
|
self.projStack = QStackedWidget()
|
||||||
@@ -156,12 +155,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.splitDocs.addWidget(self.docEditor)
|
self.splitDocs.addWidget(self.docEditor)
|
||||||
self.splitDocs.addWidget(self.splitView)
|
self.splitDocs.addWidget(self.splitView)
|
||||||
|
|
||||||
# Splitter : Project Outlie / Outline Details
|
|
||||||
self.splitOutline = QSplitter(Qt.Vertical)
|
|
||||||
self.splitOutline.addWidget(self.projView)
|
|
||||||
self.splitOutline.addWidget(self.projMeta)
|
|
||||||
self.splitOutline.setSizes(self.mainConf.getOutlinePanePos())
|
|
||||||
|
|
||||||
# Splitter : Project Tree / Main Tabs
|
# Splitter : Project Tree / Main Tabs
|
||||||
self.splitMain = QSplitter(Qt.Horizontal)
|
self.splitMain = QSplitter(Qt.Horizontal)
|
||||||
self.splitMain.setContentsMargins(0, 0, mPx, 0)
|
self.splitMain.setContentsMargins(0, 0, mPx, 0)
|
||||||
@@ -172,7 +165,7 @@ class GuiMain(QMainWindow):
|
|||||||
# Main Stack : Editor / Outline
|
# Main Stack : Editor / Outline
|
||||||
self.mainStack = QStackedWidget()
|
self.mainStack = QStackedWidget()
|
||||||
self.mainStack.addWidget(self.splitMain)
|
self.mainStack.addWidget(self.splitMain)
|
||||||
self.mainStack.addWidget(self.splitOutline)
|
self.mainStack.addWidget(self.projView)
|
||||||
self.mainStack.currentChanged.connect(self._mainStackChanged)
|
self.mainStack.currentChanged.connect(self._mainStackChanged)
|
||||||
|
|
||||||
# Indices of Splitter Widgets
|
# Indices of Splitter Widgets
|
||||||
@@ -185,7 +178,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
# Indices of Tab Widgets
|
# Indices of Tab Widgets
|
||||||
self.idxEditorView = self.mainStack.indexOf(self.splitMain)
|
self.idxEditorView = self.mainStack.indexOf(self.splitMain)
|
||||||
self.idxOutlineView = self.mainStack.indexOf(self.splitOutline)
|
self.idxOutlineView = self.mainStack.indexOf(self.projView)
|
||||||
self.idxTreeView = self.projStack.indexOf(self.treeView)
|
self.idxTreeView = self.projStack.indexOf(self.treeView)
|
||||||
self.idxNovelView = self.projStack.indexOf(self.novelView)
|
self.idxNovelView = self.projStack.indexOf(self.novelView)
|
||||||
|
|
||||||
@@ -293,7 +286,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.docEditor.clearEditor()
|
self.docEditor.clearEditor()
|
||||||
self.docEditor.setDictionaries()
|
self.docEditor.setDictionaries()
|
||||||
self.closeDocViewer()
|
self.closeDocViewer()
|
||||||
self.projMeta.clearDetails()
|
self.projView.clearOutline()
|
||||||
|
|
||||||
# General
|
# General
|
||||||
self.statusBar.clearStatus()
|
self.statusBar.clearStatus()
|
||||||
@@ -904,7 +897,7 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
logger.verbose("Forcing a rebuild of the Project Outline")
|
logger.verbose("Forcing a rebuild of the Project Outline")
|
||||||
self._changeView(nwView.OUTLINE)
|
self._changeView(nwView.OUTLINE)
|
||||||
self.projView.refreshTree(overRide=True)
|
self.projView.refreshView(overRide=True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -955,7 +948,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.treeView.initTree()
|
self.treeView.initTree()
|
||||||
self.novelView.initTree()
|
self.novelView.initTree()
|
||||||
self.projView.initOutline()
|
self.projView.initOutline()
|
||||||
self.projMeta.initDetails()
|
|
||||||
self._updateStatusWordCount()
|
self._updateStatusWordCount()
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -1192,7 +1184,7 @@ class GuiMain(QMainWindow):
|
|||||||
if not self.isFocusMode:
|
if not self.isFocusMode:
|
||||||
self.mainConf.setMainPanePos(self.splitMain.sizes())
|
self.mainConf.setMainPanePos(self.splitMain.sizes())
|
||||||
self.mainConf.setDocPanePos(self.splitDocs.sizes())
|
self.mainConf.setDocPanePos(self.splitDocs.sizes())
|
||||||
self.mainConf.setOutlinePanePos(self.splitOutline.sizes())
|
self.mainConf.setOutlinePanePos(self.projView.splitSizes())
|
||||||
if self.viewMeta.isVisible():
|
if self.viewMeta.isVisible():
|
||||||
self.mainConf.setViewPanePos(self.splitView.sizes())
|
self.mainConf.setViewPanePos(self.splitView.sizes())
|
||||||
|
|
||||||
@@ -1500,7 +1492,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.projStack.setCurrentWidget(self.novelView)
|
self.projStack.setCurrentWidget(self.novelView)
|
||||||
|
|
||||||
elif view == nwView.OUTLINE:
|
elif view == nwView.OUTLINE:
|
||||||
self.mainStack.setCurrentWidget(self.splitOutline)
|
self.mainStack.setCurrentWidget(self.projView)
|
||||||
|
|
||||||
elif view == nwView.DETAILS:
|
elif view == nwView.DETAILS:
|
||||||
self.showProjectDetailsDialog()
|
self.showProjectDetailsDialog()
|
||||||
@@ -1590,7 +1582,7 @@ class GuiMain(QMainWindow):
|
|||||||
logger.verbose("Novel tree changed while Outline tab active")
|
logger.verbose("Novel tree changed while Outline tab active")
|
||||||
if self.hasProject:
|
if self.hasProject:
|
||||||
self.treeView.flushTreeOrder()
|
self.treeView.flushTreeOrder()
|
||||||
self.projView.refreshTree(novelChanged=True)
|
self.projView.refreshView(novelChanged=True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1623,7 +1615,7 @@ class GuiMain(QMainWindow):
|
|||||||
elif tabIndex == self.idxOutlineView:
|
elif tabIndex == self.idxOutlineView:
|
||||||
logger.verbose("Project outline tab activated")
|
logger.verbose("Project outline tab activated")
|
||||||
if self.hasProject:
|
if self.hasProject:
|
||||||
self.projView.refreshTree()
|
self.projView.refreshView()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user