# -*- coding: utf-8 -*- """novelWriter GUI Document Viewer novelWriter – GUI Document Viewer =================================== Class holding the document html viewer File History: Created: 2019-05-10 [0.0.1] """ import logging import nw from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QTextBrowser from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor from nw.convert import ToHtml from nw.constants import nwAlert, nwItemType, nwDocAction logger = logging.getLogger(__name__) class GuiDocViewer(QTextBrowser): def __init__(self, theParent, theProject): QTextBrowser.__init__(self) logger.debug("Initialising DocViewer ...") # Class Variables self.mainConf = nw.CONFIG self.theProject = theProject self.theParent = theParent self.theTheme = theParent.theTheme self.theHandle = None self.qDocument = self.document() self.setMinimumWidth(300) self.setOpenExternalLinks(False) self.initViewer() theOpt = QTextOption() if self.mainConf.doJustify: theOpt.setAlignment(Qt.AlignJustify) self.qDocument.setDefaultTextOption(theOpt) self.anchorClicked.connect(self._linkClicked) self.setFocusPolicy(Qt.StrongFocus) logger.debug("DocViewer initialisation complete") return def clearViewer(self): self.clear() self.setSearchPaths([""]) return True def initViewer(self): """Set editor settings from main config. """ self._makeStyleSheet() # Set Font theFont = QFont() if self.mainConf.textFont is None: # If none is defined, set the default back to config self.mainConf.textFont = self.qDocument.defaultFont().family() theFont.setFamily(self.mainConf.textFont) theFont.setPointSize(self.mainConf.textSize) self.setFont(theFont) docPalette = self.palette() docPalette.setColor(QPalette.Base, QColor(*self.theTheme.colBack)) docPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText)) self.setPalette(docPalette) self.qDocument.setDocumentMargin(self.mainConf.textMargin) theOpt = QTextOption() if self.mainConf.doJustify: theOpt.setAlignment(Qt.AlignJustify) self.qDocument.setDefaultTextOption(theOpt) # If we have a document open, we should reload it in case the font changed if self.theHandle is not None: tHandle = self.theHandle self.clearViewer() self.loadText(tHandle) return True def loadText(self, tHandle): tItem = self.theProject.getItem(tHandle) if tItem is None: logger.warning("Item not found") return False if tItem.itemType != nwItemType.FILE: return False logger.debug("Generating preview for item %s" % tHandle) sPos = self.verticalScrollBar().value() aDoc = ToHtml(self.theProject, self.theParent) aDoc.setPreview(True, self.mainConf.viewComments) aDoc.setText(tHandle) aDoc.doAutoReplace() aDoc.tokenizeText() aDoc.doConvert() aDoc.doPostProcessing() self.setHtml(aDoc.theResult) if self.theHandle == tHandle: self.verticalScrollBar().setValue(sPos) self.theHandle = tHandle self.theProject.setLastViewed(tHandle) self.theParent.viewMeta.refreshReferences(tHandle) return True def reloadText(self): self.loadText(self.theHandle) return def loadFromTag(self, theTag): logger.debug("Loading document from tag '%s'" % theTag) if theTag in self.theParent.theIndex.tagIndex.keys(): theTarget = self.theParent.theIndex.tagIndex[theTag] else: logger.debug("The tag was not found in the index") return False if len(theTarget) != 3: # Just to make sure the index is not messed up return False self.loadText(theTarget[1]) return True def docAction(self, theAction): logger.verbose("Requesting action: %s" % theAction.name) if self.theHandle is None: logger.error("No document open") return False if theAction == nwDocAction.CUT: self.copy() elif theAction == nwDocAction.COPY: self.copy() elif theAction == nwDocAction.SEL_ALL: self._makeSelection(QTextCursor.Document) elif theAction == nwDocAction.SEL_PARA: self._makeSelection(QTextCursor.BlockUnderCursor) else: logger.debug("Unknown or unsupported document action %s" % str(theAction)) return False return True ## # Internal Functions ## def _makeSelection(self, selMode): theCursor = self.textCursor() theCursor.clearSelection() theCursor.select(selMode) self.setTextCursor(theCursor) return 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): styleSheet = ( "body {{" " color: rgb({tColR},{tColG},{tColB});" " font-size: {textSize:.1f}pt;" "}}\n" "h1, h2, h3, h4 {{" " color: rgb({hColR},{hColG},{hColB});" "}}\n" "a {{" " color: rgb({aColR},{aColG},{aColB});" "}}\n" "mark {{" " color: rgb({eColR},{eColG},{eColB});" "}}\n" "table {{" " margin: 10px 0px;" "}}\n" "td {{" " padding: 0px 4px;" "}}\n" ".tags {{" " color: rgb({kColR},{kColG},{kColB});" " font-wright: bold;" "}}\n" ".comment {{" " color: rgb({cColR},{cColG},{cColB});" " margin-left: 1em;" " margin-right: 1em;" "}}\n" ).format( textSize = self.mainConf.textSize, preSize = self.mainConf.textSize*0.9, tColR = self.theTheme.colText[0], tColG = self.theTheme.colText[1], tColB = self.theTheme.colText[2], hColR = self.theTheme.colHead[0], hColG = self.theTheme.colHead[1], hColB = self.theTheme.colHead[2], cColR = self.theTheme.colComm[0], cColG = self.theTheme.colComm[1], cColB = self.theTheme.colComm[2], eColR = self.theTheme.colEmph[0], eColG = self.theTheme.colEmph[1], eColB = self.theTheme.colEmph[2], aColR = self.theTheme.colVal[0], aColG = self.theTheme.colVal[1], aColB = self.theTheme.colVal[2], kColR = self.theTheme.colKey[0], kColG = self.theTheme.colKey[1], kColB = self.theTheme.colKey[2], ) self.qDocument.setDefaultStyleSheet(styleSheet) return True # END Class GuiDocViewer