Details panel now has all the data

This commit is contained in:
Veronica K. B. Olsen
2020-06-03 20:40:25 +02:00
parent 8199c2f4e9
commit 4334e62148
5 changed files with 256 additions and 18 deletions
+16 -6
View File
@@ -95,6 +95,7 @@ class Config:
self.projColWidth = [140, 55, 140] self.projColWidth = [140, 55, 140]
self.mainPanePos = [300, 800] self.mainPanePos = [300, 800]
self.docPanePos = [400, 400] self.docPanePos = [400, 400]
self.outlnPanePos = [500, 150]
self.isFullScreen = False self.isFullScreen = False
## Project ## Project
@@ -342,6 +343,9 @@ class Config:
self.docPanePos = self._parseLine( self.docPanePos = self._parseLine(
cnfParse, cnfSec, "docpane", self.CNF_LIST, self.docPanePos cnfParse, cnfSec, "docpane", self.CNF_LIST, self.docPanePos
) )
self.outlnPanePos = self._parseLine(
cnfParse, cnfSec, "outlinepane", self.CNF_LIST, self.outlnPanePos
)
self.isFullScreen = self._parseLine( self.isFullScreen = self._parseLine(
cnfParse, cnfSec, "fullscreen", self.CNF_BOOL, self.isFullScreen cnfParse, cnfSec, "fullscreen", self.CNF_BOOL, self.isFullScreen
) )
@@ -481,12 +485,13 @@ class Config:
## Sizes ## Sizes
cnfSec = "Sizes" cnfSec = "Sizes"
cnfParse.add_section(cnfSec) cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec,"geometry", self._packList(self.winGeometry)) cnfParse.set(cnfSec,"geometry", self._packList(self.winGeometry))
cnfParse.set(cnfSec,"treecols", self._packList(self.treeColWidth)) cnfParse.set(cnfSec,"treecols", self._packList(self.treeColWidth))
cnfParse.set(cnfSec,"projcols", self._packList(self.projColWidth)) cnfParse.set(cnfSec,"projcols", self._packList(self.projColWidth))
cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos)) cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos))
cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos)) cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos))
cnfParse.set(cnfSec,"fullscreen", str(self.isFullScreen)) cnfParse.set(cnfSec,"outlinepane", self._packList(self.outlnPanePos))
cnfParse.set(cnfSec,"fullscreen", str(self.isFullScreen))
## Project ## Project
cnfSec = "Project" cnfSec = "Project"
@@ -700,6 +705,11 @@ class Config:
self.confChanged = True self.confChanged = True
return True return True
def setOutlinePanePos(self, panePos):
self.outlnPanePos = panePos
self.confChanged = True
return True
def setShowRefPanel(self, checkState): def setShowRefPanel(self, checkState):
self.showRefPanel = checkState self.showRefPanel = checkState
self.confChanged = True self.confChanged = True
+15 -11
View File
@@ -268,6 +268,21 @@ class GuiDocViewer(QTextBrowser):
logger.verbose("Cursor moved to line %d" % theLine) logger.verbose("Cursor moved to line %d" % theLine)
return True return True
##
# Slots
##
def _linkClicked(self, theURL):
"""Slot for a link in the document being clicked.
"""
theLink = theURL.url()
logger.verbose("Clicked link: '%s'" % theLink)
if len(theLink) > 0:
theBits = theLink.split("=")
if len(theBits) == 2:
self.loadFromTag(theBits[1])
return
## ##
# Events # Events
## ##
@@ -293,17 +308,6 @@ class GuiDocViewer(QTextBrowser):
self.setTextCursor(theCursor) self.setTextCursor(theCursor)
return return
def _linkClicked(self, theURL):
"""Slot for a link in the document being clicked.
"""
theLink = theURL.url()
logger.verbose("Clicked link: '%s'" % theLink)
if len(theLink) > 0:
theBits = theLink.split("=")
if len(theBits) == 2:
self.loadFromTag(theBits[1])
return
def _makeStyleSheet(self): def _makeStyleSheet(self):
"""Generate an appropriate style sheet for the document viewer, """Generate an appropriate style sheet for the document viewer,
based on the current syntax highlighter theme, based on the current syntax highlighter theme,
+14
View File
@@ -100,6 +100,7 @@ class GuiOutline(QTreeWidget):
self.setExpandsOnDoubleClick(False) self.setExpandsOnDoubleClick(False)
self.setDragEnabled(False) self.setDragEnabled(False)
self.itemDoubleClicked.connect(self._treeDoubleClick) self.itemDoubleClicked.connect(self._treeDoubleClick)
self.itemSelectionChanged.connect(self._itemSelected)
iPx = self.theTheme.textIconSize iPx = self.theTheme.textIconSize
self.setIconSize(QSize(iPx, iPx)) self.setIconSize(QSize(iPx, iPx))
@@ -198,6 +199,18 @@ class GuiOutline(QTreeWidget):
self.theParent.openDocument(tHandle, tLine - 1) self.theParent.openDocument(tHandle, tLine - 1)
return return
def _itemSelected(self):
"""Extract the handle and line number of the currently selected
title, and send it to the details panel.
"""
selItems = self.selectedItems()
if selItems:
tHandle = selItems[0].data(self.colIndex[nwOutline.TITLE], Qt.UserRole)
sTitle = selItems[0].data(self.colIndex[nwOutline.LINE], Qt.UserRole)
logger.verbose("User selected entry %s:%s" % (tHandle, sTitle))
self.theParent.projMeta.showItem(tHandle, sTitle)
return
def _headerRightClick(self, clickPos): def _headerRightClick(self, clickPos):
"""Show the header column menu. """Show the header column menu.
""" """
@@ -415,6 +428,7 @@ class GuiOutline(QTreeWidget):
newItem.setText(self.colIndex[nwOutline.LABEL], nwItem.itemName) newItem.setText(self.colIndex[nwOutline.LABEL], nwItem.itemName)
newItem.setIcon(self.colIndex[nwOutline.LABEL], self.theTheme.getIcon("proj_document")) newItem.setIcon(self.colIndex[nwOutline.LABEL], self.theTheme.getIcon("proj_document"))
newItem.setText(self.colIndex[nwOutline.LINE], sTitle[1:].lstrip("0")) newItem.setText(self.colIndex[nwOutline.LINE], sTitle[1:].lstrip("0"))
newItem.setData(self.colIndex[nwOutline.LINE], Qt.UserRole, sTitle)
newItem.setText(self.colIndex[nwOutline.SYNOP], novIdx["synopsis"]) newItem.setText(self.colIndex[nwOutline.SYNOP], novIdx["synopsis"])
newItem.setText(self.colIndex[nwOutline.CCOUNT], str(novIdx["cCount"])) newItem.setText(self.colIndex[nwOutline.CCOUNT], str(novIdx["cCount"]))
newItem.setText(self.colIndex[nwOutline.WCOUNT], str(novIdx["wCount"])) newItem.setText(self.colIndex[nwOutline.WCOUNT], str(novIdx["wCount"]))
+209 -1
View File
@@ -30,13 +30,22 @@ import nw
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QWidget QWidget, QGridLayout, QHBoxLayout, QGroupBox, QLabel, QSizePolicy
) )
from nw.constants import nwLabels, nwKeyWords
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiOutlineDetails(QWidget): class GuiOutlineDetails(QWidget):
LVL_MAP = {
"H1" : "Title",
"H2" : "Chapter",
"H3" : "Scene",
"H4" : "Section"
}
def __init__(self, theParent): def __init__(self, theParent):
QWidget.__init__(self, theParent) QWidget.__init__(self, theParent)
@@ -49,8 +58,207 @@ class GuiOutlineDetails(QWidget):
self.theIndex = theParent.theIndex self.theIndex = theParent.theIndex
self.optState = theParent.theProject.optState self.optState = theParent.theProject.optState
# Sizes
minTitle = self.theTheme.getTextWidth("X"*30)
maxTitle = self.theTheme.getTextWidth("X"*50)
wCount = self.theTheme.getTextWidth("99,999")
hSpace = int(0.5*self.theTheme.fontPixelSize)
vSpace = int(0.3*self.theTheme.fontPixelSize)
# Details Area
self.titleLabel = QLabel("<b>Title</b>")
self.levelLabel = QLabel("<b>Level</b>")
self.fileLabel = QLabel("<b>Document</b>")
self.titleValue = QLabel("")
self.levelValue = QLabel("")
self.fileValue = QLabel("")
self.titleValue.setMinimumWidth(minTitle)
self.titleValue.setMaximumWidth(maxTitle)
self.levelValue.setMinimumWidth(minTitle)
self.levelValue.setMaximumWidth(maxTitle)
self.fileValue.setMinimumWidth(minTitle)
self.fileValue.setMaximumWidth(maxTitle)
# Stats Area
self.cCLabel = QLabel("<b>Characters</b>")
self.wCLabel = QLabel("<b>Words</b>")
self.pCLabel = QLabel("<b>Paragraphs</b>")
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>Synopsis</b>")
self.synopValue = QLabel("")
self.synopLWrap = QHBoxLayout()
self.synopValue.setWordWrap(True)
self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
self.synopValue.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
self.synopLWrap.addWidget(self.synopValue, 1)
# Tags
self.povKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.POV_KEY])
self.chrKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY])
self.pltKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY])
self.timKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.TIME_KEY])
self.wldKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY])
self.objKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY])
self.entKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY])
self.cstKeyLabel = QLabel("<b>%s</b>" % nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY])
self.povKeyValue = QLabel("")
self.chrKeyValue = QLabel("")
self.pltKeyValue = QLabel("")
self.timKeyValue = QLabel("")
self.wldKeyValue = QLabel("")
self.objKeyValue = QLabel("")
self.entKeyValue = QLabel("")
self.cstKeyValue = QLabel("")
self.povKeyValue.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)
# Selected Item Details
self.mainGroup = QGroupBox("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.levelLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.mainForm.addWidget(self.levelValue, 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.fileLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.mainForm.addWidget(self.fileValue, 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("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.addWidget(self.povKeyValue, 0, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.chrKeyLabel, 1, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.chrKeyValue, 1, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.pltKeyLabel, 2, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.pltKeyValue, 2, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.timKeyLabel, 3, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.timKeyValue, 3, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.wldKeyLabel, 4, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.wldKeyValue, 4, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.objKeyLabel, 5, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.objKeyValue, 5, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.entKeyLabel, 6, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.entKeyValue, 6, 1, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.cstKeyLabel, 7, 0, 1, 1, Qt.AlignTop | Qt.AlignLeft)
self.tagsForm.addWidget(self.cstKeyValue, 7, 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.outerBox = QHBoxLayout()
self.outerBox.addWidget(self.mainGroup, 0)
self.outerBox.addWidget(self.tagsGroup, 1)
self.outerBox.addStretch(1)
self.setLayout(self.outerBox)
logger.debug("GuiOutlineDetails initialisation complete") logger.debug("GuiOutlineDetails initialisation complete")
return return
def showItem(self, tHandle, sTitle):
"""Update the content of the tree with the given handle and line
number pointing to a header.
"""
try:
nwItem = self.theProject.projTree[tHandle]
novIdx = self.theIndex.novelIndex[tHandle][sTitle]
theRefs = self.theIndex.getReferences(tHandle, sTitle)
except:
return False
self.titleValue.setText(novIdx["title"])
if novIdx["level"] in self.LVL_MAP:
self.levelValue.setText(self.LVL_MAP[novIdx["level"]])
else:
self.levelValue.setText("Unknown")
self.fileValue.setText(nwItem.itemName)
self.cCValue.setText("{:n}".format(novIdx["cCount"]))
self.wCValue.setText("{:n}".format(novIdx["pCount"]))
self.pCValue.setText("{:n}".format(novIdx["wCount"]))
self.synopValue.setText(novIdx["synopsis"])
self.synopValue.adjustSize()
# print(self.mainForm.sizeHint().width())
# self.synopValue.setSizePolicy() (self.mainForm.sizeHint().width())
self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_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.theParent.docViewer.loadFromTag(theBits[1])
self.theParent.tabWidget.setCurrentWidget(self.theParent.splitView)
return
##
# Internal Functions
##
def _formatTags(self, theRefs, theKey):
"""Format the tags as clickable links.
"""
if theKey not in theKey:
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 # END Class GuiOutlineDetails
+2
View File
@@ -139,6 +139,7 @@ class GuiMain(QMainWindow):
self.splitOutline = QSplitter(Qt.Vertical) self.splitOutline = QSplitter(Qt.Vertical)
self.splitOutline.addWidget(self.projView) self.splitOutline.addWidget(self.projView)
self.splitOutline.addWidget(self.projMeta) self.splitOutline.addWidget(self.projMeta)
self.splitOutline.setSizes(self.mainConf.outlnPanePos)
self.tabWidget = QTabWidget() self.tabWidget = QTabWidget()
self.tabWidget.setTabPosition(QTabWidget.East) self.tabWidget.setTabPosition(QTabWidget.East)
@@ -849,6 +850,7 @@ class GuiMain(QMainWindow):
if not self.isZenMode: if not self.isZenMode:
self.mainConf.setMainPanePos(self.splitMain.sizes()) self.mainConf.setMainPanePos(self.splitMain.sizes())
self.mainConf.setDocPanePos(self.splitView.sizes()) self.mainConf.setDocPanePos(self.splitView.sizes())
self.mainConf.setOutlinePanePos(self.splitOutline.sizes())
self.mainConf.saveConfig() self.mainConf.saveConfig()
self.reportConfErr() self.reportConfErr()