diff --git a/nw/assets/icons/fallback/reference-dark.svg b/nw/assets/icons/fallback/reference-dark.svg
new file mode 100644
index 00000000..e57b19b0
--- /dev/null
+++ b/nw/assets/icons/fallback/reference-dark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/fallback/reference.svg b/nw/assets/icons/fallback/reference.svg
new file mode 100644
index 00000000..09202533
--- /dev/null
+++ b/nw/assets/icons/fallback/reference.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/fallback/sticky-off-dark.svg b/nw/assets/icons/fallback/sticky-off-dark.svg
new file mode 100644
index 00000000..f571d5c9
--- /dev/null
+++ b/nw/assets/icons/fallback/sticky-off-dark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/fallback/sticky-off.svg b/nw/assets/icons/fallback/sticky-off.svg
new file mode 100644
index 00000000..57b2b498
--- /dev/null
+++ b/nw/assets/icons/fallback/sticky-off.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/fallback/sticky-on-dark.svg b/nw/assets/icons/fallback/sticky-on-dark.svg
new file mode 100644
index 00000000..62c6a66b
--- /dev/null
+++ b/nw/assets/icons/fallback/sticky-on-dark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/fallback/sticky-on.svg b/nw/assets/icons/fallback/sticky-on.svg
new file mode 100644
index 00000000..3473b82f
--- /dev/null
+++ b/nw/assets/icons/fallback/sticky-on.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_dark/bookmark.svg b/nw/assets/icons/typicons_colour_dark/bookmark.svg
new file mode 100644
index 00000000..e56ebbee
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_dark/bookmark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_dark/icons.conf b/nw/assets/icons/typicons_colour_dark/icons.conf
index f55adaa9..3f8b547f 100644
--- a/nw/assets/icons/typicons_colour_dark/icons.conf
+++ b/nw/assets/icons/typicons_colour_dark/icons.conf
@@ -49,3 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
+reference = bookmark.svg
+sticky-on = pin.svg
+sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_colour_dark/pin-outline.svg b/nw/assets/icons/typicons_colour_dark/pin-outline.svg
new file mode 100644
index 00000000..478ff1a6
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_dark/pin-outline.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_dark/pin.svg b/nw/assets/icons/typicons_colour_dark/pin.svg
new file mode 100644
index 00000000..ea040440
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_dark/pin.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_light/bookmark.svg b/nw/assets/icons/typicons_colour_light/bookmark.svg
new file mode 100644
index 00000000..3936ba30
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_light/bookmark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_light/icons.conf b/nw/assets/icons/typicons_colour_light/icons.conf
index af948e10..b080af1d 100644
--- a/nw/assets/icons/typicons_colour_light/icons.conf
+++ b/nw/assets/icons/typicons_colour_light/icons.conf
@@ -49,3 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
+reference = bookmark.svg
+sticky-on = pin.svg
+sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_colour_light/pin-outline.svg b/nw/assets/icons/typicons_colour_light/pin-outline.svg
new file mode 100644
index 00000000..9091424e
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_light/pin-outline.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_colour_light/pin.svg b/nw/assets/icons/typicons_colour_light/pin.svg
new file mode 100644
index 00000000..372928f7
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_light/pin.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_dark/bookmark.svg b/nw/assets/icons/typicons_grey_dark/bookmark.svg
new file mode 100644
index 00000000..e57b19b0
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_dark/bookmark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_dark/icons.conf b/nw/assets/icons/typicons_grey_dark/icons.conf
index b8b24e46..0a68c931 100644
--- a/nw/assets/icons/typicons_grey_dark/icons.conf
+++ b/nw/assets/icons/typicons_grey_dark/icons.conf
@@ -49,3 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
+reference = bookmark.svg
+sticky-on = pin.svg
+sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_grey_dark/pin-outline.svg b/nw/assets/icons/typicons_grey_dark/pin-outline.svg
new file mode 100644
index 00000000..f571d5c9
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_dark/pin-outline.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_dark/pin.svg b/nw/assets/icons/typicons_grey_dark/pin.svg
new file mode 100644
index 00000000..62c6a66b
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_dark/pin.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_light/bookmark.svg b/nw/assets/icons/typicons_grey_light/bookmark.svg
new file mode 100644
index 00000000..42556b6b
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_light/bookmark.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_light/icons.conf b/nw/assets/icons/typicons_grey_light/icons.conf
index 9d99741c..2c019496 100644
--- a/nw/assets/icons/typicons_grey_light/icons.conf
+++ b/nw/assets/icons/typicons_grey_light/icons.conf
@@ -49,3 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
+reference = bookmark.svg
+sticky-on = pin.svg
+sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_grey_light/pin-outline.svg b/nw/assets/icons/typicons_grey_light/pin-outline.svg
new file mode 100644
index 00000000..57b2b498
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_light/pin-outline.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/assets/icons/typicons_grey_light/pin.svg b/nw/assets/icons/typicons_grey_light/pin.svg
new file mode 100644
index 00000000..3473b82f
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_light/pin.svg
@@ -0,0 +1,31 @@
+
+
diff --git a/nw/config.py b/nw/config.py
index ca9cab7b..5c734981 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -96,6 +96,7 @@ class Config:
self.projColWidth = [140, 55, 140]
self.mainPanePos = [300, 800]
self.docPanePos = [400, 400]
+ self.viewPanePos = [500, 150]
self.outlnPanePos = [500, 150]
self.isFullScreen = False
@@ -363,6 +364,9 @@ class Config:
self.docPanePos = self._parseLine(
cnfParse, cnfSec, "docpane", self.CNF_LIST, self.docPanePos
)
+ self.viewPanePos = self._parseLine(
+ cnfParse, cnfSec, "viewpane", self.CNF_LIST, self.viewPanePos
+ )
self.outlnPanePos = self._parseLine(
cnfParse, cnfSec, "outlinepane", self.CNF_LIST, self.outlnPanePos
)
@@ -513,6 +517,7 @@ class Config:
cnfParse.set(cnfSec,"projcols", self._packList(self.projColWidth))
cnfParse.set(cnfSec,"mainpane", self._packList(self.mainPanePos))
cnfParse.set(cnfSec,"docpane", self._packList(self.docPanePos))
+ cnfParse.set(cnfSec,"viewpane", self._packList(self.viewPanePos))
cnfParse.set(cnfSec,"outlinepane", self._packList(self.outlnPanePos))
cnfParse.set(cnfSec,"fullscreen", str(self.isFullScreen))
@@ -730,6 +735,11 @@ class Config:
self.confChanged = True
return True
+ def setViewPanePos(self, panePos):
+ self.viewPanePos = [int(x/self.guiScale) for x in panePos]
+ self.confChanged = True
+ return True
+
def setOutlinePanePos(self, panePos):
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
self.confChanged = True
@@ -770,6 +780,9 @@ class Config:
def getDocPanePos(self):
return [int(x*self.guiScale) for x in self.docPanePos]
+ def getViewPanePos(self):
+ return [int(x*self.guiScale) for x in self.viewPanePos]
+
def getOutlinePanePos(self):
return [int(x*self.guiScale) for x in self.outlnPanePos]
diff --git a/nw/core/options.py b/nw/core/options.py
index 12593c0c..abab6a65 100644
--- a/nw/core/options.py
+++ b/nw/core/options.py
@@ -77,7 +77,7 @@ class OptionState():
"headerOrder",
"columnWidth",
"columnHidden",
- ])
+ ]),
}
return
diff --git a/nw/core/project.py b/nw/core/project.py
index 45480820..caa81b09 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -579,6 +579,7 @@ class NWProject():
def closeProject(self):
"""Close the current project and clear all meta data.
"""
+ self.optState.saveSettings()
self.projTree.writeToCFiles()
self._appendSessionStats()
self._clearLockFile()
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index 312744d6..4073dcc6 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -2,8 +2,7 @@
from nw.gui.about import GuiAbout
from nw.gui.build import GuiBuildNovel
-from nw.gui.docbars import GuiDocTitleBar, GuiSearchBar
-from nw.gui.docdetails import GuiDocViewDetails
+from nw.gui.docbars import GuiDocTitleBar, GuiSearchBar, GuiDocViewDetails
from nw.gui.doceditor import GuiDocEditor
from nw.gui.docmerge import GuiDocMerge
from nw.gui.docsplit import GuiDocSplit
diff --git a/nw/gui/docbars.py b/nw/gui/docbars.py
index f35556df..839ae024 100644
--- a/nw/gui/docbars.py
+++ b/nw/gui/docbars.py
@@ -7,7 +7,9 @@
File History:
Created: 2019-09-29 [0.2.1] GuiSearchBar
+ Created: 2019-10-31 [0.3.2] GuiDocViewDetails
Created: 2020-04-25 [0.4.5] GuiDocTitleBar
+ Created: 2020-06-09 [0.8.0] GuiDocViewFooter
This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen
@@ -30,10 +32,10 @@ import logging
import nw
from PyQt5.QtCore import Qt, QSize
-from PyQt5.QtGui import QPalette, QColor
+from PyQt5.QtGui import QPalette, QColor, QIcon
from PyQt5.QtWidgets import (
qApp, QWidget, QFrame, QGridLayout, QLabel, QLineEdit, QPushButton,
- QHBoxLayout, QToolButton
+ QHBoxLayout, QToolButton, QScrollArea
)
from nw.constants import nwDocAction, nwUnicode
@@ -170,14 +172,14 @@ class GuiSearchBar(QWidget):
class GuiDocTitleBar(QWidget):
- def __init__(self, theParent, theProject, isEditor):
+ def __init__(self, theParent, isEditor):
QWidget.__init__(self, theParent)
logger.debug("Initialising GuiDocTitleBar ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
- self.theProject = theProject
+ self.theProject = theParent.theProject
self.theTheme = theParent.theTheme
self.theHandle = None
self.isEditor = isEditor
@@ -351,3 +353,198 @@ class GuiDocTitleBar(QWidget):
return
# END Class GuiDocTitleBar
+
+class GuiDocViewFooter(QWidget):
+
+ def __init__(self, theParent):
+ QWidget.__init__(self, theParent)
+
+ logger.debug("Initialising GuiDocViewFooter ...")
+
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theTheme = theParent.theTheme
+ self.optState = theParent.theProject.optState
+ self.viewMeta = theParent.theParent.viewMeta
+ self.theHandle = None
+
+ # Make a QPalette that matches the Syntax Theme
+ self.thePalette = QPalette()
+ self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
+ self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
+
+ fPx = int(0.9*self.theTheme.fontPixelSize)
+ hSp = self.mainConf.pxInt(6)
+
+ # Main Widget Settings
+ self.setContentsMargins(0, 0, 0, 0)
+ self.setAutoFillBackground(True)
+ self.setPalette(self.thePalette)
+
+ buttonStyle = (
+ "QToolButton {{border: none; background: transparent;}} "
+ "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
+ ).format(*self.theTheme.colText)
+
+ # Show/Hide Details
+ self.showHide = QToolButton(self)
+ self.showHide.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.showHide.setStyleSheet(buttonStyle)
+ self.showHide.setIcon(self.theTheme.getIcon("reference"))
+ self.showHide.setIconSize(QSize(fPx, fPx))
+ self.showHide.setFixedSize(QSize(fPx, fPx))
+ self.showHide.clicked.connect(self._doShowHide)
+
+ # Sticky Button
+ stickyOn = self.theTheme.getPixmap("sticky-on", (fPx, fPx))
+ stickyOff = self.theTheme.getPixmap("sticky-off", (fPx, fPx))
+ stickyIcon = QIcon()
+ stickyIcon.addPixmap(stickyOn, QIcon.Normal, QIcon.On)
+ stickyIcon.addPixmap(stickyOff, QIcon.Normal, QIcon.Off)
+ self.stickyRefs = QToolButton(self)
+ self.stickyRefs.setCheckable(True)
+ self.stickyRefs.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.stickyRefs.setStyleSheet(buttonStyle)
+ self.stickyRefs.setIcon(stickyIcon)
+ self.stickyRefs.setIconSize(QSize(fPx, fPx))
+ self.stickyRefs.setFixedSize(QSize(fPx, fPx))
+ self.stickyRefs.toggled.connect(self._doToggleSticky)
+
+ # Labels
+ self.lblRefs = QLabel("References")
+ self.lblRefs.setBuddy(self.showHide)
+ self.lblRefs.setIndent(0)
+ self.lblRefs.setMargin(0)
+ self.lblRefs.setContentsMargins(0, 0, 0, 0)
+ self.lblRefs.setAutoFillBackground(True)
+ self.lblRefs.setFixedHeight(fPx)
+ self.lblRefs.setAlignment(Qt.AlignLeft | Qt.AlignTop)
+ self.lblRefs.setPalette(self.thePalette)
+
+ self.lblSticky = QLabel("Sticky")
+ self.lblSticky.setBuddy(self.stickyRefs)
+ self.lblSticky.setIndent(0)
+ self.lblSticky.setMargin(0)
+ self.lblSticky.setContentsMargins(0, 0, 0, 0)
+ self.lblSticky.setAutoFillBackground(True)
+ self.lblSticky.setFixedHeight(fPx)
+ self.lblSticky.setAlignment(Qt.AlignLeft | Qt.AlignTop)
+ self.lblSticky.setPalette(self.thePalette)
+
+ lblFont = self.font()
+ lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
+ self.lblRefs.setFont(lblFont)
+ self.lblSticky.setFont(lblFont)
+
+ # Assemble Layout
+ self.outerBox = QHBoxLayout()
+ self.outerBox.setSpacing(hSp)
+ self.outerBox.addWidget(self.showHide, 0)
+ self.outerBox.addWidget(self.lblRefs, 0)
+ self.outerBox.addWidget(self.stickyRefs, 0)
+ self.outerBox.addWidget(self.lblSticky, 0)
+ self.outerBox.addStretch(1)
+ self.setLayout(self.outerBox)
+
+ logger.debug("GuiDocViewFooter initialisation complete")
+
+ return
+
+ ##
+ # Slots
+ ##
+
+ def _doShowHide(self):
+ """Toggle the expand/collapse of the panel.
+ """
+ isVisible = self.viewMeta.isVisible()
+ self.viewMeta.setVisible(not isVisible)
+ return
+
+ def _doToggleSticky(self, theState):
+ """Toggle the sticky flag for the reference panel.
+ """
+ logger.verbose("Reference sticky is %s" % str(theState))
+ self.theParent.stickyRef = theState
+ if not theState and self.theParent.theHandle is not None:
+ self.viewMeta.refreshReferences(self.theParent.theHandle)
+ return
+
+# END Class GuiDocViewFooter
+
+class GuiDocViewDetails(QScrollArea):
+
+ def __init__(self, theParent):
+ QScrollArea.__init__(self, theParent)
+
+ logger.debug("Initialising DocViewDetails ...")
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theProject = theParent.theProject
+ self.theTheme = theParent.theTheme
+ self.currHandle = None
+
+ self.refList = QLabel("None")
+ self.refList.setWordWrap(True)
+ self.refList.setAlignment(Qt.AlignTop)
+ self.refList.setScaledContents(True)
+ self.refList.linkActivated.connect(self._linkClicked)
+
+ hCol = self.palette().highlight().color()
+ self.linkStyle = "style='color: rgb({0},{1},{2})'".format(
+ *self.theTheme.colLink
+ )
+
+ # Assemble
+ self.outerWidget = QWidget()
+ self.outerBox = QHBoxLayout()
+ self.outerBox.addWidget(self.refList, 1)
+
+ self.outerWidget.setLayout(self.outerBox)
+ self.setWidget(self.outerWidget)
+
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+ self.setWidgetResizable(True)
+ self.setMinimumHeight(self.mainConf.pxInt(50))
+
+ logger.debug("DocViewDetails initialisation complete")
+
+ return
+
+ def refreshReferences(self, tHandle):
+ """Update the current list of document references from the
+ project index.
+ """
+ self.currHandle = tHandle
+ if self.theParent.docViewer.stickyRef:
+ return
+
+ theRefs = self.theParent.theIndex.getBackReferenceList(tHandle)
+ theList = []
+ for tHandle in theRefs:
+ tItem = self.theProject.projTree[tHandle]
+ if tItem is not None:
+ theList.append("%s" % (
+ tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
+ ))
+
+ self.refList.setText(", ".join(theList))
+
+ return
+
+ ##
+ # Internal Functions
+ ##
+
+ def _linkClicked(self, theLink):
+ """Capture the link-click and forward it to the document viewer
+ class for handling.
+ """
+ logger.verbose("Clicked link: '%s'" % theLink)
+ if len(theLink) == 27:
+ tHandle = theLink[6:19]
+ self.theParent.viewDocument(tHandle, theLink)
+ return
+
+# END Class GuiDocViewDetails
diff --git a/nw/gui/docdetails.py b/nw/gui/docdetails.py
deleted file mode 100644
index 7c4ec8f7..00000000
--- a/nw/gui/docdetails.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# -*- coding: utf-8 -*-
-"""novelWriter GUI DocView Details
-
- novelWriter – GUI DocView Details
-===================================
- Class holding the document view details panel
-
- File History:
- Created: 2019-10-31 [0.3.2]
-
- This file is a part of novelWriter
- Copyright 2020, 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 .
-"""
-
-import logging
-import nw
-
-from PyQt5.QtCore import Qt, QSize
-from PyQt5.QtWidgets import (
- QWidget, QLabel, QScrollArea, QFrame, QToolButton, QCheckBox, QGridLayout
-)
-
-logger = logging.getLogger(__name__)
-
-class GuiDocViewDetails(QWidget):
-
- def __init__(self, theParent):
- QWidget.__init__(self, theParent)
-
- logger.debug("Initialising DocViewDetails ...")
- self.mainConf = nw.CONFIG
- self.theParent = theParent
- self.theProject = theParent.theProject
- self.theTheme = theParent.theTheme
- self.currHandle = None
-
- x4 = self.mainConf.pxInt(4)
- x80 = self.mainConf.pxInt(80)
- iPx = self.theTheme.textIconSize
-
- self.outerBox = QGridLayout(self)
- self.outerBox.setContentsMargins(0, 0, 0, 0)
- self.outerBox.setHorizontalSpacing(0)
- self.outerBox.setVerticalSpacing(x4)
-
- 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.setIconSize(QSize(iPx, iPx))
- 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)
- self.refList.setAlignment(Qt.AlignTop)
- self.refList.setScaledContents(True)
- self.refList.linkActivated.connect(self._linkClicked)
-
- self.scrollBox = QScrollArea()
- self.scrollBox.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- self.scrollBox.setFrameStyle(QFrame.NoFrame)
- self.scrollBox.setWidgetResizable(True)
- self.scrollBox.setFixedHeight(x80)
- self.scrollBox.setWidget(self.refList)
-
- 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)
-
- self._doShowHide(self.mainConf.showRefPanel)
-
- logger.debug("DocViewDetails initialisation complete")
-
- return
-
- def refreshReferences(self, tHandle):
- """Update the current list of document references from the
- project index.
- """
- self.currHandle = tHandle
-
- if self.isSticky.isChecked():
- return
-
- theRefs = self.theParent.theIndex.getBackReferenceList(tHandle)
- theList = []
- for tHandle in theRefs:
- tItem = self.theProject.projTree[tHandle]
- if tItem is not None:
- theList.append("%s" % (
- tHandle, theRefs[tHandle], tItem.itemName
- ))
-
- self.refList.setText(", ".join(theList))
- self.refList.adjustSize()
-
- return
-
- ##
- # Internal Functions
- ##
-
- def _linkClicked(self, theLink):
- """Capture the link-click and forward it to the document viewer
- class for handling.
- """
- logger.verbose("Clicked link: '%s'" % theLink)
- if len(theLink) == 27:
- tHandle = theLink[6:19]
- self.theParent.viewDocument(tHandle, theLink)
- return
-
- def _doShowHide(self, chState):
- """Toggle the expand/collapse of the panel.
- """
- self.scrollBox.setVisible(chState)
- self.mainConf.setShowRefPanel(chState)
- if chState:
- self.showHide.setArrowType(Qt.DownArrow)
- else:
- self.showHide.setArrowType(Qt.RightArrow)
- return
-
- def _doSticky(self, chState):
- """Toggle the sticky feature of the references.
- """
- if not chState and self.currHandle is not None:
- self.refreshReferences(self.currHandle)
- return
-
-# END Class GuiDocViewDetails
diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py
index 81c37e04..d3b6eb93 100644
--- a/nw/gui/doceditor.py
+++ b/nw/gui/doceditor.py
@@ -85,7 +85,7 @@ class GuiDocEditor(QTextEdit):
self.qDocument.contentsChange.connect(self._docChange)
# Document Title
- self.docTitle = GuiDocTitleBar(self, self.theProject, isEditor=True)
+ self.docTitle = GuiDocTitleBar(self, isEditor=True)
self.docTitle.setGeometry(0, 0, self.docTitle.width(), self.docTitle.height())
self.setViewportMargins(0, self.docTitle.height(), 0, 0)
diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py
index c43c6cc0..0648111b 100644
--- a/nw/gui/docviewer.py
+++ b/nw/gui/docviewer.py
@@ -34,7 +34,7 @@ from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
from nw.core import ToHtml
from nw.constants import nwAlert, nwItemType, nwDocAction
-from nw.gui.docbars import GuiDocTitleBar
+from nw.gui.docbars import GuiDocTitleBar, GuiDocViewFooter
logger = logging.getLogger(__name__)
@@ -57,10 +57,10 @@ class GuiDocViewer(QTextBrowser):
self.setOpenExternalLinks(False)
self.initViewer()
- # Document Title
- self.docTitle = GuiDocTitleBar(self, self.theProject, isEditor=False)
- self.docTitle.setGeometry(0, 0, self.docTitle.width(), self.docTitle.height())
- self.setViewportMargins(0, self.docTitle.height(), 0, 0)
+ # Document Title and Footer
+ self.docTitle = GuiDocTitleBar(self, isEditor=False)
+ self.docFooter = GuiDocViewFooter(self)
+ self.stickyRef = False
theOpt = QTextOption()
if self.mainConf.doJustify:
@@ -233,15 +233,17 @@ class GuiDocViewer(QTextBrowser):
tB = self.lineWidth()
tW = self.width() - 2*tB - sW
tH = self.docTitle.height()
+ fH = self.docFooter.height()
+ fY = self.height() - fH - tB
tT = self.mainConf.getTextMargin() - tH
+ bT = self.mainConf.getTextMargin() - fH
self.docTitle.setGeometry(tB, tB, tW, tH)
- self.setViewportMargins(0, tH, 0, 0)
+ self.docFooter.setGeometry(tB, fY, tW, fH)
+ self.setViewportMargins(0, tH, 0, fH)
docFormat = self.qDocument.rootFrame().frameFormat()
- if tT > 0:
- docFormat.setTopMargin(tT)
- else:
- docFormat.setTopMargin(0)
+ docFormat.setTopMargin(max(0, tT))
+ docFormat.setBottomMargin(max(0, bT))
self.qDocument.blockSignals(True)
self.qDocument.rootFrame().setFrameFormat(docFormat)
diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py
index 739b1c37..9a010559 100644
--- a/nw/gui/outlinedetails.py
+++ b/nw/gui/outlinedetails.py
@@ -216,11 +216,9 @@ class GuiOutlineDetails(QScrollArea):
self.outerBox = QHBoxLayout()
self.outerBox.addWidget(self.mainGroup, 0)
self.outerBox.addWidget(self.tagsGroup, 1)
- # self.outerBox.addStretch(1)
self.outerWidget.setLayout(self.outerBox)
self.setWidget(self.outerWidget)
- self.show()
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
diff --git a/nw/gui/theme.py b/nw/gui/theme.py
index 08b18691..78b2b44d 100644
--- a/nw/gui/theme.py
+++ b/nw/gui/theme.py
@@ -537,6 +537,9 @@ class GuiIcons:
"maximise" : (None, None),
"minimise" : (None, None),
"refresh" : (None, None),
+ "reference" : (None, None),
+ "sticky-on" : (None, None),
+ "sticky-off" : (None, None),
## Other Icons
"warning" : (QStyle.SP_MessageBoxWarning, "dialog-warning"),
diff --git a/nw/guimain.py b/nw/guimain.py
index 84dfbd21..e34ff448 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -92,8 +92,8 @@ class GuiMain(QMainWindow):
self.statusBar = GuiMainStatus(self)
self.treeView = GuiProjectTree(self)
self.docEditor = GuiDocEditor(self)
- self.docViewer = GuiDocViewer(self)
self.viewMeta = GuiDocViewDetails(self)
+ self.docViewer = GuiDocViewer(self)
self.searchBar = GuiSearchBar(self)
self.treeMeta = GuiItemDetails(self)
self.projView = GuiOutline(self)
@@ -120,19 +120,15 @@ class GuiMain(QMainWindow):
self.docEdit.addWidget(self.docEditor)
self.editPane.setLayout(self.docEdit)
- self.viewPane = QWidget()
- self.docView = QVBoxLayout()
- self.docView.setContentsMargins(0, 0, 0, 0)
- self.docView.setSpacing(self.mainConf.pxInt(2))
- self.docView.addWidget(self.docViewer)
- self.docView.addWidget(self.viewMeta)
- self.docView.setStretch(0, 1)
- self.viewPane.setLayout(self.docView)
+ self.splitView = QSplitter(Qt.Vertical)
+ self.splitView.addWidget(self.docViewer)
+ self.splitView.addWidget(self.viewMeta)
+ self.splitView.setSizes(self.mainConf.getViewPanePos())
- self.splitView = QSplitter(Qt.Horizontal)
- self.splitView.setOpaqueResize(False)
- self.splitView.addWidget(self.editPane)
- self.splitView.addWidget(self.viewPane)
+ self.splitDocs = QSplitter(Qt.Horizontal)
+ self.splitDocs.setOpaqueResize(False)
+ self.splitDocs.addWidget(self.editPane)
+ self.splitDocs.addWidget(self.splitView)
self.splitOutline = QSplitter(Qt.Vertical)
self.splitOutline.addWidget(self.projView)
@@ -142,7 +138,7 @@ class GuiMain(QMainWindow):
self.tabWidget = QTabWidget()
self.tabWidget.setTabPosition(QTabWidget.East)
self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}")
- self.tabWidget.addTab(self.splitView, "Editor")
+ self.tabWidget.addTab(self.splitDocs, "Editor")
self.tabWidget.addTab(self.splitOutline, "Outline")
self.tabWidget.currentChanged.connect(self._mainTabChanged)
@@ -156,20 +152,23 @@ class GuiMain(QMainWindow):
self.setCentralWidget(self.splitMain)
- self.idxTree = self.splitMain.indexOf(self.treePane)
- self.idxMain = self.splitMain.indexOf(self.tabWidget)
- self.idxEditor = self.splitView.indexOf(self.editPane)
- self.idxViewer = self.splitView.indexOf(self.viewPane)
-
- self.idxTabEdit = self.tabWidget.indexOf(self.splitView)
- self.idxTabProj = self.tabWidget.indexOf(self.splitOutline)
+ self.idxTree = self.splitMain.indexOf(self.treePane)
+ self.idxMain = self.splitMain.indexOf(self.tabWidget)
+ self.idxEditor = self.splitDocs.indexOf(self.editPane)
+ self.idxViewer = self.splitDocs.indexOf(self.splitView)
+ self.idxViewDoc = self.splitView.indexOf(self.docViewer)
+ self.idxViewMeta = self.splitView.indexOf(self.viewMeta)
+ self.idxTabEdit = self.tabWidget.indexOf(self.splitDocs)
+ self.idxTabProj = self.tabWidget.indexOf(self.splitOutline)
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.splitDocs.setCollapsible(self.idxEditor, False)
+ self.splitDocs.setCollapsible(self.idxViewer, True)
+ self.splitView.setCollapsible(self.idxViewDoc, False)
+ self.splitView.setCollapsible(self.idxViewMeta, False)
- self.viewPane.setVisible(False)
+ self.splitView.setVisible(False)
self.searchBar.setVisible(False)
# Build the Tree View
@@ -353,7 +352,7 @@ class GuiMain(QMainWindow):
self.theIndex.clearIndex()
self.clearGUI()
self.hasProject = False
- self.tabWidget.setCurrentWidget(self.splitView)
+ self.tabWidget.setCurrentWidget(self.splitDocs)
return saveOK
@@ -371,7 +370,7 @@ class GuiMain(QMainWindow):
return False
# Switch main tab to editor view
- self.tabWidget.setCurrentWidget(self.splitView)
+ self.tabWidget.setCurrentWidget(self.splitDocs)
# Try to open the project
if not self.theProject.openProject(projFile):
@@ -475,7 +474,7 @@ class GuiMain(QMainWindow):
"""
if self.hasProject:
self.closeDocument()
- self.tabWidget.setCurrentWidget(self.splitView)
+ self.tabWidget.setCurrentWidget(self.splitDocs)
if self.docEditor.loadText(tHandle, tLine):
if changeFocus:
self.docEditor.setFocus()
@@ -508,16 +507,17 @@ class GuiMain(QMainWindow):
return False
# Make sure main tab is in Editor view
- self.tabWidget.setCurrentWidget(self.splitView)
+ self.tabWidget.setCurrentWidget(self.splitDocs)
if self.docViewer.loadText(tHandle):
- if not self.viewPane.isVisible():
+ if not self.splitView.isVisible():
bPos = self.splitMain.sizes()
- self.viewPane.setVisible(True)
+ self.splitView.setVisible(True)
vPos = [0, 0]
vPos[0] = int(bPos[1]/2)
vPos[1] = bPos[1] - vPos[0]
- self.splitView.setSizes(vPos)
+ self.splitDocs.setSizes(vPos)
+ self.viewMeta.setVisible(self.mainConf.showRefPanel)
self.docViewer.navigateTo(navLink)
return True
@@ -842,16 +842,22 @@ class GuiMain(QMainWindow):
return False
logger.info("Exiting %s" % nw.__package__)
- if self.hasProject:
- self.closeProject(True)
+ if not self.isZenMode:
+ self.mainConf.setMainPanePos(self.splitMain.sizes())
+ self.mainConf.setDocPanePos(self.splitDocs.sizes())
+ self.mainConf.setOutlinePanePos(self.splitOutline.sizes())
+ if self.viewMeta.isVisible():
+ self.mainConf.setViewPanePos(self.splitView.sizes())
+
+ self.mainConf.setShowRefPanel(self.viewMeta.isVisible())
self.mainConf.setTreeColWidths(self.treeView.getColumnSizes())
if not self.mainConf.isFullScreen:
self.mainConf.setWinSize(self.width(), self.height())
- if not self.isZenMode:
- self.mainConf.setMainPanePos(self.splitMain.sizes())
- self.mainConf.setDocPanePos(self.splitView.sizes())
- self.mainConf.setOutlinePanePos(self.splitOutline.sizes())
+
+ if self.hasProject:
+ self.closeProject(True)
+
self.mainConf.saveConfig()
self.reportConfErr()
@@ -874,13 +880,15 @@ class GuiMain(QMainWindow):
return
def closeDocViewer(self):
+ """Close the document view panel.
+ """
self.docViewer.clearViewer()
self.theProject.setLastViewed(None)
bPos = self.splitMain.sizes()
- self.viewPane.setVisible(False)
+ self.splitView.setVisible(False)
vPos = [bPos[1], 0]
- self.splitView.setSizes(vPos)
- return not self.viewPane.isVisible()
+ self.splitDocs.setSizes(vPos)
+ return not self.splitView.isVisible()
def toggleZenMode(self):
"""Main GUI Zen Mode hides tree, view pane and optionally also
@@ -893,7 +901,7 @@ class GuiMain(QMainWindow):
self.isZenMode = not self.isZenMode
if self.isZenMode:
logger.debug("Activating Zen mode")
- self.tabWidget.setCurrentWidget(self.splitView)
+ self.tabWidget.setCurrentWidget(self.splitDocs)
else:
logger.debug("Deactivating Zen mode")
@@ -903,10 +911,10 @@ class GuiMain(QMainWindow):
self.mainMenu.setVisible(isVisible)
self.tabWidget.tabBar().setVisible(isVisible)
- if self.viewPane.isVisible():
- self.viewPane.setVisible(False)
+ if self.splitView.isVisible():
+ self.splitView.setVisible(False)
elif self.docViewer.theHandle is not None:
- self.viewPane.setVisible(True)
+ self.splitView.setVisible(True)
return True
diff --git a/tests/reference/novelwriter.conf b/tests/reference/novelwriter.conf
index 2ecde509..bafeaaed 100644
--- a/tests/reference/novelwriter.conf
+++ b/tests/reference/novelwriter.conf
@@ -1,5 +1,5 @@
[Main]
-timestamp = 2020-06-03 20:42:03
+timestamp = 2020-06-09 23:05:17
theme = default
syntax = default_light
icons = typicons_colour_light
@@ -13,6 +13,7 @@ treecols = 120, 30, 50
projcols = 140, 55, 140
mainpane = 300, 800
docpane = 400, 400
+viewpane = 500, 150
outlinepane = 500, 150
fullscreen = False