Merge pull request #109 from vkbo/docview_meta

Docview Meta Data
This commit is contained in:
Veronica K. Berglyd Olsen
2019-10-31 21:55:57 +01:00
committed by GitHub
6 changed files with 256 additions and 35 deletions
+50 -3
View File
@@ -23,6 +23,18 @@ class ToHtml(Tokenizer):
def __init__(self, theProject, theParent):
Tokenizer.__init__(self, theProject, theParent)
self.forPreview = False
return
def setPreview(self, forPreview):
"""If we're using this class to generate markdown preview, we need to make a few changes to
formatting, which is selected by this flag.
"""
self.forPreview = forPreview
if forPreview:
self.doKeywords = True
return
def doAutoReplace(self):
@@ -103,10 +115,45 @@ class ToHtml(Tokenizer):
self.theResult += "<div class='comment'>%s</div>\n" % tText
elif tType == self.T_KEYWORD and self.doKeywords:
self.theResult += "<pre>@%s</pre>\n" % tText
# print(self.theResult)
self.theResult += self._formatTags(tText)
return
##
# Internal Functions
##
def _formatTags(self, tText):
if not self.forPreview:
return "<pre>@%s</pre>\n" % tText
theLabel = {
"@tag" : "Tag",
"@pov" : "Point of View",
"@char" : "Character(s)",
"@plot" : "Plot",
"@time" : "Time",
"@location" : "Location(s)",
"@object" : "Object(s)",
"@custom" : "Custom",
}
tText = "@"+tText
isValid, theBits, thePos = self.theParent.theIndex.scanThis(tText)
if not isValid or not theBits:
return ""
retText = ""
refTags = []
if theBits[0] in theLabel:
retText += "<span class='tags'>%s:</span>&nbsp;" % theLabel[theBits[0]]
for tTag in theBits[1:]:
refTags.append("<a href='#%s=%s'>%s</a>" % (
theBits[0][1:], tTag, tTag
))
retText += ", ".join(refTags)
return "<div>%s</div>" % retText
# END Class ToHtml
+60 -6
View File
@@ -19,7 +19,7 @@ from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor
from nw.convert.tokenizer import Tokenizer
from nw.convert.text.tohtml import ToHtml
from nw.enum import nwItemType
from nw.enum import nwAlert, nwItemType
logger = logging.getLogger(__name__)
@@ -46,6 +46,8 @@ class GuiDocViewer(QTextBrowser):
theOpt.setAlignment(Qt.AlignJustify)
self.qDocument.setDefaultTextOption(theOpt)
self.anchorClicked.connect(self._linkClicked)
logger.debug("DocViewer initialisation complete")
return
@@ -102,6 +104,7 @@ class GuiDocViewer(QTextBrowser):
logger.debug("Generating preview for item %s" % tHandle)
sPos = self.verticalScrollBar().value()
aDoc = ToHtml(self.theProject, self.theParent)
aDoc.setPreview(True)
aDoc.setText(tHandle)
aDoc.doAutoReplace()
aDoc.tokenizeText()
@@ -113,6 +116,8 @@ class GuiDocViewer(QTextBrowser):
self.theHandle = tHandle
self.theProject.setLastViewed(tHandle)
self.theParent.docMeta.refreshReferences(tHandle)
return True
def loadFromTag(self, theTag):
@@ -137,22 +142,59 @@ class GuiDocViewer(QTextBrowser):
# Internal Functions
##
def _linkClicked(self, theURL):
theLink = theURL.url()
tHandle = None
onLine = 0
theTag = ""
if len(theLink) > 0:
theBits = theLink.split("=")
if len(theBits) == 2:
theTag = theBits[1]
tHandle, onLine = self.theParent.theIndex.getTagSource(theBits[1])
if tHandle is None:
self.theParent.makeAlert((
"Could not find the reference for tag '%s'. It either doesn't exist, or the index "
"is out of date. The index can be updated from the Tools menu.") % theTag,
nwAlert.ERROR
)
return
else:
self.loadText(tHandle)
return
def _makeStyleSheet(self):
self.qDocument.setDefaultStyleSheet((
styleSheet = (
"body {{"
" font-size: {textSize}pt;"
" font-size: {textSize:.1f}pt;"
" color: rgb({tColR},{tColG},{tColB});"
"}}\n"
"h1, h2, h3, h4 {{"
"h1 {{"
" color: rgb({hColR},{hColG},{hColB});"
" font-size: {h1Size:.1f}pt;"
"}}\n"
"h2 {{"
" color: rgb({hColR},{hColG},{hColB});"
" font-size: {h2Size:.1f}pt;"
"}}\n"
"h3 {{"
" color: rgb({hColR},{hColG},{hColB});"
" font-size: {h3Size:.1f}pt;"
"}}\n"
"h4 {{"
" color: rgb({hColR},{hColG},{hColB});"
" font-size: {h4Size:.1f}pt;"
"}}\n"
"a {{"
" color: rgb({aColR},{aColG},{aColB});"
"}}\n"
"pre {{"
" color: rgb({cColR},{cColG},{cColB});"
" font-size: {preSize}pt;"
" font-size: {preSize:.1f}pt;"
"}}\n"
"mark {{"
" color: rgb({eColR},{eColG},{eColB});"
@@ -163,9 +205,17 @@ class GuiDocViewer(QTextBrowser):
"td {{"
" padding: 0px 4px;"
"}}\n"
".tags {{"
" color: rgb({kColR},{kColG},{kColB});"
" font-wright: bold;"
"}}\n"
).format(
textSize = self.mainConf.textSize,
preSize = self.mainConf.textSize*0.9,
h1Size = self.mainConf.textSize*1.8,
h2Size = self.mainConf.textSize*1.6,
h3Size = self.mainConf.textSize*1.4,
h4Size = self.mainConf.textSize*1.2,
tColR = self.theTheme.colText[0],
tColG = self.theTheme.colText[1],
tColB = self.theTheme.colText[2],
@@ -181,7 +231,11 @@ class GuiDocViewer(QTextBrowser):
aColR = self.theTheme.colLink[0],
aColG = self.theTheme.colLink[1],
aColB = self.theTheme.colLink[2],
))
kColR = self.theTheme.colKey[0],
kColG = self.theTheme.colKey[1],
kColB = self.theTheme.colKey[2],
)
self.qDocument.setDefaultStyleSheet(styleSheet)
return True
+82
View File
@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"""novelWriter GUI DocView Details
novelWriter GUI DocView Details
===================================
Class holding the document view details panel
File History:
Created: 2019-09-31 [0.3.2]
"""
import logging
import nw
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QGroupBox, QComboBox
from nw.constants import nwLabels
logger = logging.getLogger(__name__)
class GuiDocViewDetails(QWidget):
def __init__(self, theParent, theProject):
QWidget.__init__(self, theParent)
logger.debug("Initialising DocViewDetails ...")
self.mainConf = nw.CONFIG
self.debugGUI = self.mainConf.debugGUI
self.theParent = theParent
self.theProject = theProject
self.outerBox = QHBoxLayout(self)
self.outerBox.setContentsMargins(4,4,4,4)
self.refTags = QGroupBox("Referenced From", self)
self.refTagsForm = QHBoxLayout(self.refTags)
self.refTags.setLayout(self.refTagsForm)
self.refList = QLabel("None")
self.refList.linkActivated.connect(self._linkClicked)
self.refTagsForm.addWidget(self.refList)
self.outerBox.addWidget(self.refTags)
self.setLayout(self.outerBox)
self.setContentsMargins(0,0,0,0)
logger.debug("DocViewDetails initialisation complete")
return
def refreshReferences(self, tHandle):
theRefs = self.theParent.theIndex.buildReferenceList(tHandle)
if theRefs:
self.setVisible(True)
else:
self.setVisible(False)
return
theList = []
for tHandle in theRefs:
tItem = self.theProject.getItem(tHandle)
if tItem is not None:
theList.append("<a href='#tag=%s'>%s</a>" % (tHandle,tItem.itemName))
self.refList.setText(", ".join(theList))
return
##
# Internal Functions
##
def _linkClicked(self, theLink):
if len(theLink) == 18:
tHandle = theLink[-13:]
self.theParent.viewDocument(tHandle)
return
# END Class GuiDocViewDetails
+2 -2
View File
@@ -25,7 +25,7 @@ class GuiMainStatus(QStatusBar):
def __init__(self, theParent):
QStatusBar.__init__(self, theParent)
logger.debug("Initialising GuiMainStatus ...")
logger.debug("Initialising MainStatus ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
@@ -80,7 +80,7 @@ class GuiMainStatus(QStatusBar):
self.sessionTimer.timeout.connect(self._updateTime)
self.sessionTimer.start()
logger.debug("GuiMainStatus initialisation complete")
logger.debug("MainStatus initialisation complete")
self.clearStatus()
+33 -24
View File
@@ -31,6 +31,7 @@ from nw.gui.elements.docviewer import GuiDocViewer
from nw.gui.elements.docdetails import GuiDocDetails
from nw.gui.elements.searchbar import GuiSearchBar
from nw.gui.elements.noticebar import GuiNoticeBar
from nw.gui.elements.viewdetails import GuiDocViewDetails
from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.projecteditor import GuiProjectEditor
from nw.gui.dialogs.export import GuiExport
@@ -72,14 +73,15 @@ class GuiMain(QMainWindow):
self.setWindowIcon(QIcon(path.join(self.mainConf.appIcon)))
# Main GUI Elements
self.statusBar = GuiMainStatus(self)
self.noticeBar = GuiNoticeBar(self)
self.docEditor = GuiDocEditor(self, self.theProject)
self.docViewer = GuiDocViewer(self, self.theProject)
self.docDetails = GuiDocDetails(self, self.theProject)
self.searchBar = GuiSearchBar(self)
self.treeView = GuiDocTree(self, self.theProject)
self.mainMenu = GuiMainMenu(self, self.theProject)
self.statusBar = GuiMainStatus(self)
self.noticeBar = GuiNoticeBar(self)
self.docEditor = GuiDocEditor(self, self.theProject)
self.docViewer = GuiDocViewer(self, self.theProject)
self.docMeta = GuiDocViewDetails(self, self.theProject)
self.searchBar = GuiSearchBar(self)
self.treeMeta = GuiDocDetails(self, self.theProject)
self.treeView = GuiDocTree(self, self.theProject)
self.mainMenu = GuiMainMenu(self, self.theProject)
# Minor Gui Elements
self.statusIcons = []
@@ -90,20 +92,27 @@ class GuiMain(QMainWindow):
self.treeBox = QVBoxLayout()
self.treeBox.setContentsMargins(0,0,0,0)
self.treeBox.addWidget(self.treeView)
self.treeBox.addWidget(self.docDetails)
self.treeBox.addWidget(self.treeMeta)
self.treePane.setLayout(self.treeBox)
self.docPane = QFrame()
self.editPane = QFrame()
self.docEdit = QVBoxLayout()
self.docEdit.setContentsMargins(0,0,0,0)
self.docEdit.addWidget(self.searchBar)
self.docEdit.addWidget(self.noticeBar)
self.docEdit.addWidget(self.docEditor)
self.editPane.setLayout(self.docEdit)
self.viewPane = QFrame()
self.docView = QVBoxLayout()
self.docView.setContentsMargins(0,0,0,0)
self.docView.addWidget(self.searchBar)
self.docView.addWidget(self.noticeBar)
self.docView.addWidget(self.docEditor)
self.docPane.setLayout(self.docView)
self.docView.addWidget(self.docViewer)
self.docView.addWidget(self.docMeta)
self.viewPane.setLayout(self.docView)
self.splitView = QSplitter(Qt.Horizontal)
self.splitView.addWidget(self.docPane)
self.splitView.addWidget(self.docViewer)
self.splitView.addWidget(self.editPane)
self.splitView.addWidget(self.viewPane)
self.splitView.splitterMoved.connect(self._splitViewMove)
self.splitMain = QSplitter(Qt.Horizontal)
@@ -117,15 +126,15 @@ class GuiMain(QMainWindow):
self.idxTree = self.splitMain.indexOf(self.treePane)
self.idxMain = self.splitMain.indexOf(self.splitView)
self.idxEditor = self.splitView.indexOf(self.docPane)
self.idxViewer = self.splitView.indexOf(self.docViewer)
self.idxEditor = self.splitView.indexOf(self.editPane)
self.idxViewer = self.splitView.indexOf(self.viewPane)
self.splitMain.setCollapsible(self.idxTree, False)
self.splitMain.setCollapsible(self.idxMain, False)
self.splitView.setCollapsible(self.idxEditor, False)
self.splitView.setCollapsible(self.idxViewer, True)
self.docViewer.setVisible(False)
self.viewPane.setVisible(False)
self.searchBar.setVisible(False)
# Build The Tree View
@@ -365,9 +374,9 @@ class GuiMain(QMainWindow):
logger.debug("No document selected, giving up")
return False
if self.docViewer.loadText(tHandle) and not self.docViewer.isVisible():
if self.docViewer.loadText(tHandle) and not self.viewPane.isVisible():
bPos = self.splitMain.sizes()
self.docViewer.setVisible(True)
self.viewPane.setVisible(True)
vPos = [0,0]
vPos[0] = int(bPos[1]/2)
vPos[1] = bPos[1]-vPos[0]
@@ -669,11 +678,11 @@ class GuiMain(QMainWindow):
self.docViewer.clearViewer()
self.theProject.setLastViewed(None)
bPos = self.splitMain.sizes()
self.docViewer.setVisible(False)
self.viewPane.setVisible(False)
vPos = [bPos[1],0]
self.splitView.setSizes(vPos)
self.docEditor.changeWidth()
return not self.docViewer.isVisible()
return not self.viewPane.isVisible()
##
# Internal Functions
@@ -739,7 +748,7 @@ class GuiMain(QMainWindow):
def _treeSingleClick(self):
sHandle = self.treeView.getSelectedHandle()
if sHandle is not None:
self.docDetails.buildViewBox(sHandle)
self.treeMeta.buildViewBox(sHandle)
return
def _treeDoubleClick(self, tItem, colNo):
+29
View File
@@ -319,6 +319,35 @@ class NWIndex():
return True
def buildReferenceList(self, theHandle):
theRefs = {}
tItem = self.theProject.getItem(theHandle)
if theHandle is None:
return theRefs
theTag = None
for tTag in self.tagIndex:
if theHandle == self.tagIndex[tTag][1]:
theTag = tTag
break
if theTag is not None:
for tHandle in self.refIndex:
for nLine, tKey, tTag, nTitle in self.refIndex[tHandle]:
if tTag == theTag:
theRefs[tHandle] = nLine
return theRefs
def getTagSource(self, theTag):
if theTag in self.tagIndex:
theRef = self.tagIndex[theTag]
if len(theRef) == 3:
return theRef[1], theRef[0]
return None, 0
def buildTagNovelMap(self, theTags, theFilters=None):
tagMap = {}