From 18f45c5e1149ceb29362a3a03afda5debf0ffe56 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 31 Oct 2019 22:55:52 +0100 Subject: [PATCH 1/3] Using scrollarea for the viewer reference panel --- nw/gui/elements/viewdetails.py | 13 ++++++++++--- nw/gui/winmain.py | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/nw/gui/elements/viewdetails.py b/nw/gui/elements/viewdetails.py index 5d8b7325..b9f5bb5a 100644 --- a/nw/gui/elements/viewdetails.py +++ b/nw/gui/elements/viewdetails.py @@ -15,7 +15,7 @@ import nw from PyQt5.QtCore import Qt from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QGroupBox +from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QGroupBox, QScrollArea, QFrame from nw.constants import nwLabels @@ -45,7 +45,14 @@ class GuiDocViewDetails(QWidget): self.refList.setScaledContents(True) self.refList.linkActivated.connect(self._linkClicked) - self.refTagsForm.addWidget(self.refList) + self.scrollBox = QScrollArea() + self.scrollBox.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.scrollBox.setFrameStyle(QFrame.NoFrame) + self.scrollBox.setWidgetResizable(True) + self.scrollBox.setMaximumHeight(300) + self.scrollBox.setWidget(self.refList) + + self.refTagsForm.addWidget(self.scrollBox) self.outerBox.addWidget(self.refTags) self.setLayout(self.outerBox) self.setContentsMargins(0,0,0,0) @@ -70,7 +77,7 @@ class GuiDocViewDetails(QWidget): theList.append("%s" % (tHandle,tItem.itemName)) self.refList.setText(", ".join(theList)) - self.refList.setMaximumHeight(300) + self.refList.adjustSize() return diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py index 6c70e981..680ae966 100644 --- a/nw/gui/winmain.py +++ b/nw/gui/winmain.py @@ -108,6 +108,7 @@ class GuiMain(QMainWindow): self.docView.setContentsMargins(0,0,0,0) self.docView.addWidget(self.docViewer) self.docView.addWidget(self.docMeta) + self.docView.setStretch(0, 1) self.viewPane.setLayout(self.docView) self.splitView = QSplitter(Qt.Horizontal) From 8a0a3ca6122c3536d616d6cee6a3c16ef8a38f7b Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 31 Oct 2019 23:31:11 +0100 Subject: [PATCH 2/3] Updated comments in NWIndex class --- nw/project/index.py | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/nw/project/index.py b/nw/project/index.py index 86236a61..45e5753a 100644 --- a/nw/project/index.py +++ b/nw/project/index.py @@ -8,18 +8,6 @@ File History: Created: 2019-05-27 [0.1.4] -Structure: - - We need to scan all files to get the novel layout. This is done by heading depth. Each heading -is recorded in a sorted list. Each such heading again can have a set of meta tags. - In the other class root folders, each file can have a tag which the meta tags in the novel files -point to. These tags should be stored in a dictionary where the tag is the key pointing to a single -file handle. That way we can do lookups on both keys and values. - The timeline view then consists of novel header elements in the horizontal header, possibly just -truncated to a Ch or Sc abbreviation, possibly with a number. This can be extracted from the item -layout. The vertical header column is then whatever notes we want to compare against, and the links -from the novel files are dots on the row. - """ import logging @@ -85,6 +73,8 @@ class NWIndex(): ## def loadIndex(self): + """Load index from last session from the project meta folder. + """ theData = {} indexFile = path.join(self.theProject.projMeta, nwFiles.INDEX_FILE) @@ -111,6 +101,8 @@ class NWIndex(): return False def saveIndex(self): + """Save the current index as a json file in the project meta folder. + """ indexFile = path.join(self.theProject.projMeta, nwFiles.INDEX_FILE) logger.debug("Saving index file") @@ -137,6 +129,10 @@ class NWIndex(): ## def scanText(self, tHandle, theText): + """Scan a piece of text associated with a handle. This will update the indices accordingly. + This function takes the handle and text as separate inputs as we want to primarily scan the + files before we save them, unless we're rebuilding the index. + """ theItem = self.theProject.getItem(tHandle) if theItem is None: return False @@ -183,6 +179,8 @@ class NWIndex(): return True def indexTitle(self, tHandle, aLine, nLine, itemLayout): + """Save information about the title and its location in the file. + """ if aLine.startswith("# "): hDepth = 1 @@ -205,6 +203,8 @@ class NWIndex(): return True def indexNoteRef(self, tHandle, aLine, nLine, nTitle): + """Validate and save the information about a reference to a tag in another file. + """ isValid, theBits, thePos = self.scanThis(aLine) if not isValid or len(theBits) == 0: @@ -218,6 +218,8 @@ class NWIndex(): return True def indexTag(self, tHandle, aLine, nLine, itemClass): + """Validate and save the information from a tag. + """ isValid, theBits, thePos = self.scanThis(aLine) if not isValid or len(theBits) != 2: @@ -233,6 +235,9 @@ class NWIndex(): ## def scanThis(self, aLine): + """Scan a line starting with @ to check that it's valid and to split up its elements into + an array and an array of positions. The latter is needed for the syntax highlighter. + """ theBits = [] thePos = [] @@ -270,6 +275,9 @@ class NWIndex(): return True, theBits, thePos def checkThese(self, theBits, tItem): + """Check the tags against the index to see if they are valid tags. This is needed for syntax + highlighting. + """ nBits = len(theBits) isGood = [False]*nBits @@ -307,6 +315,8 @@ class NWIndex(): ## def buildNovelList(self): + """Build a list of the content of the novel. + """ self.novelList = [] self.novelOrder = [] @@ -320,6 +330,8 @@ class NWIndex(): return True def buildReferenceList(self, theHandle): + """Build a list of files referring back to our file, specified by theHandle. + """ theRefs = {} @@ -342,6 +354,8 @@ class NWIndex(): return theRefs def getTagSource(self, theTag): + """Return the source location of a given tag. + """ if theTag in self.tagIndex: theRef = self.tagIndex[theTag] if len(theRef) == 3: @@ -349,6 +363,9 @@ class NWIndex(): return None, 0 def buildTagNovelMap(self, theTags, theFilters=None): + """Build a two-dimensional map of all titles of the novel and which tags they link to from + the various meta tags. This map is used to display the timeline view. + """ tagMap = {} tagClass = {} From 537594202a6abaf4026edeebb081237d00789471 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Fri, 1 Nov 2019 21:32:20 +0100 Subject: [PATCH 3/3] Doc viewer meta pannel can be hidden, and has a sticky button --- nw/gui/elements/viewdetails.py | 58 ++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/nw/gui/elements/viewdetails.py b/nw/gui/elements/viewdetails.py index b9f5bb5a..026955b4 100644 --- a/nw/gui/elements/viewdetails.py +++ b/nw/gui/elements/viewdetails.py @@ -13,9 +13,12 @@ import logging import nw -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QGroupBox, QScrollArea, QFrame +from PyQt5.QtWidgets import ( + QWidget, QHBoxLayout, QVBoxLayout, QLabel, QGroupBox, QScrollArea, QFrame, QToolButton, + QSizePolicy, QCheckBox, QGridLayout +) from nw.constants import nwLabels @@ -31,13 +34,27 @@ class GuiDocViewDetails(QWidget): self.debugGUI = self.mainConf.debugGUI self.theParent = theParent self.theProject = theProject + self.currHandle = None - self.outerBox = QHBoxLayout(self) - self.outerBox.setContentsMargins(4,4,4,4) + self.outerBox = QGridLayout(self) + self.outerBox.setContentsMargins(0,0,0,0) + self.outerBox.setHorizontalSpacing(0) + self.outerBox.setVerticalSpacing(4) - self.refTags = QGroupBox("Referenced From", self) - self.refTagsForm = QHBoxLayout(self.refTags) - self.refTags.setLayout(self.refTagsForm) + self.refLabel = QLabel("Referenced By", self) + + self.showHide = QToolButton() + self.showHide.setStyleSheet("QToolButton { border: none; }") + self.showHide.setToolButtonStyle(Qt.ToolButtonIconOnly) + self.showHide.setArrowType(Qt.DownArrow) + self.showHide.setCheckable(True) + self.showHide.setChecked(True) + self.showHide.setIconSize(QSize(16,16)) + self.showHide.toggled.connect(self._doShowHide) + + self.isSticky = QCheckBox("Sticky") + self.isSticky.setChecked(False) + self.isSticky.toggled.connect(self._doSticky) self.refList = QLabel("None") self.refList.setWordWrap(True) @@ -50,10 +67,15 @@ class GuiDocViewDetails(QWidget): self.scrollBox.setFrameStyle(QFrame.NoFrame) self.scrollBox.setWidgetResizable(True) self.scrollBox.setMaximumHeight(300) + self.scrollBox.setMinimumHeight(60) self.scrollBox.setWidget(self.refList) - self.refTagsForm.addWidget(self.scrollBox) - self.outerBox.addWidget(self.refTags) + self.outerBox.addWidget(self.showHide, 0, 0) + self.outerBox.addWidget(self.refLabel, 0, 1) + self.outerBox.addWidget(self.isSticky, 0, 2) + self.outerBox.addWidget(self.scrollBox, 1, 1, 1, 2) + self.outerBox.setColumnStretch(1, 1) + self.setLayout(self.outerBox) self.setContentsMargins(0,0,0,0) @@ -63,6 +85,11 @@ class GuiDocViewDetails(QWidget): def refreshReferences(self, tHandle): + self.currHandle = tHandle + + if self.isSticky.isChecked(): + return + theRefs = self.theParent.theIndex.buildReferenceList(tHandle) if theRefs: self.setVisible(True) @@ -91,4 +118,17 @@ class GuiDocViewDetails(QWidget): self.theParent.viewDocument(tHandle) return + def _doShowHide(self, chState): + self.scrollBox.setVisible(chState) + if chState: + self.showHide.setArrowType(Qt.DownArrow) + else: + self.showHide.setArrowType(Qt.RightArrow) + return + + def _doSticky(self, chState): + if not chState and self.currHandle is not None: + self.refreshReferences(self.currHandle) + return + # END Class GuiDocViewDetails