diff --git a/nw/__init__.py b/nw/__init__.py
index 0d1c2088..98436cca 100644
--- a/nw/__init__.py
+++ b/nw/__init__.py
@@ -216,7 +216,9 @@ def main(sysArgs=None):
logger.addHandler(cHandle)
logger.setLevel(debugLevel)
- logger.info("This is %s %s" % (__package__, __version__))
+ logger.info("Starting %s" % __package__)
+ logger.info("Version: %s (%s)" % (__version__, __hexversion__))
+ logger.info("Last Release: %s" % __date__)
# Check Packages and Versions
errorData = []
diff --git a/nw/assets/icons/fallback/reference-dark.svg b/nw/assets/icons/fallback/reference-dark.svg
index e57b19b0..4d98eb91 100644
--- a/nw/assets/icons/fallback/reference-dark.svg
+++ b/nw/assets/icons/fallback/reference-dark.svg
@@ -5,13 +5,13 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- id="svg2608"
+ id="svg1321"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
+ id="metadata1327">
@@ -23,9 +23,9 @@
+ id="defs1325" />
+ style="stroke-width:1.25;fill:#aeaeae;fill-opacity:1"
+ id="path1319"
+ d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
diff --git a/nw/assets/icons/fallback/reference.svg b/nw/assets/icons/fallback/reference.svg
index 09202533..b39357c9 100644
--- a/nw/assets/icons/fallback/reference.svg
+++ b/nw/assets/icons/fallback/reference.svg
@@ -5,13 +5,13 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- version="1.2"
- width="24"
- height="24"
+ id="svg1321"
viewBox="0 0 24 24"
- id="svg2608">
+ height="24"
+ width="24"
+ version="1.2">
+ id="metadata1327">
@@ -23,9 +23,9 @@
+ id="defs1325" />
+ style="stroke-width:1.25;fill:#000000;fill-opacity:0.78039217"
+ id="path1319"
+ d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
diff --git a/nw/assets/icons/typicons_colour_dark/at.svg b/nw/assets/icons/typicons_colour_dark/at.svg
new file mode 100644
index 00000000..60bd3acc
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_dark/at.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 3f8b547f..33aeef93 100644
--- a/nw/assets/icons/typicons_colour_dark/icons.conf
+++ b/nw/assets/icons/typicons_colour_dark/icons.conf
@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
-reference = bookmark.svg
+reference = at.svg
sticky-on = pin.svg
sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_colour_light/at.svg b/nw/assets/icons/typicons_colour_light/at.svg
new file mode 100644
index 00000000..7f34cade
--- /dev/null
+++ b/nw/assets/icons/typicons_colour_light/at.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 b080af1d..0ba6dd6b 100644
--- a/nw/assets/icons/typicons_colour_light/icons.conf
+++ b/nw/assets/icons/typicons_colour_light/icons.conf
@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
-reference = bookmark.svg
+reference = at.svg
sticky-on = pin.svg
sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_grey_dark/at.svg b/nw/assets/icons/typicons_grey_dark/at.svg
new file mode 100644
index 00000000..4d98eb91
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_dark/at.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 0a68c931..301c74ac 100644
--- a/nw/assets/icons/typicons_grey_dark/icons.conf
+++ b/nw/assets/icons/typicons_grey_dark/icons.conf
@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
-reference = bookmark.svg
+reference = at.svg
sticky-on = pin.svg
sticky-off = pin-outline.svg
diff --git a/nw/assets/icons/typicons_grey_light/at.svg b/nw/assets/icons/typicons_grey_light/at.svg
new file mode 100644
index 00000000..b39357c9
--- /dev/null
+++ b/nw/assets/icons/typicons_grey_light/at.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 2c019496..6e98346a 100644
--- a/nw/assets/icons/typicons_grey_light/icons.conf
+++ b/nw/assets/icons/typicons_grey_light/icons.conf
@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg
cross = times.svg
hash = hash.svg
-reference = bookmark.svg
+reference = at.svg
sticky-on = pin.svg
sticky-off = pin-outline.svg
diff --git a/nw/config.py b/nw/config.py
index 5c734981..a1e222dd 100644
--- a/nw/config.py
+++ b/nw/config.py
@@ -222,6 +222,7 @@ class Config:
"""Initialise the config class. The manual setting of confPath
and dataPath is mainly intended for the test suite.
"""
+ logger.debug("Initialising Config ...")
if confPath is None:
confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
self.confPath = path.join(path.abspath(confRoot), self.appHandle)
@@ -304,6 +305,8 @@ class Config:
if self.spellLanguage is None:
self.spellLanguage = "en"
+ logger.debug("Config initialisation complete")
+
return True
def loadConfig(self):
diff --git a/nw/core/project.py b/nw/core/project.py
index caa81b09..0784fc7a 100644
--- a/nw/core/project.py
+++ b/nw/core/project.py
@@ -1041,6 +1041,7 @@ class NWProject():
return
# Then check the files in the data folder
+ logger.debug("Checking files in project content folder")
orphanFiles = []
for fileItem in listdir(self.projContent):
if not fileItem.endswith(".nwd"):
diff --git a/nw/core/spellcheck.py b/nw/core/spellcheck.py
index 6296bc60..44d0fc38 100644
--- a/nw/core/spellcheck.py
+++ b/nw/core/spellcheck.py
@@ -115,12 +115,12 @@ class NWSpellCheck():
if not path.isfile(projectDict):
return
try:
- with open(projectDict,mode="r",encoding="utf-8") as wordsFile:
+ logger.debug("Loading project word list")
+ with open(projectDict, mode="r", encoding="utf-8") as wordsFile:
for theLine in wordsFile:
theLine = theLine.strip()
if len(theLine) > 0 and theLine not in self.PROJW:
self.PROJW.append(theLine)
- logger.debug("Project word list")
logger.debug("Project word list contains %d words" % len(self.PROJW))
except Exception as e:
logger.error("Failed to load project word list")
diff --git a/nw/gui/__init__.py b/nw/gui/__init__.py
index 4073dcc6..820a2a48 100644
--- a/nw/gui/__init__.py
+++ b/nw/gui/__init__.py
@@ -2,11 +2,11 @@
from nw.gui.about import GuiAbout
from nw.gui.build import GuiBuildNovel
-from nw.gui.docbars import GuiDocTitleBar, GuiSearchBar, GuiDocViewDetails
+from nw.gui.docbars import GuiSearchBar
from nw.gui.doceditor import GuiDocEditor
from nw.gui.docmerge import GuiDocMerge
from nw.gui.docsplit import GuiDocSplit
-from nw.gui.docviewer import GuiDocViewer
+from nw.gui.docviewer import GuiDocViewer, GuiDocViewDetails
from nw.gui.itemdetails import GuiItemDetails
from nw.gui.itemeditor import GuiItemEditor
from nw.gui.mainmenu import GuiMainMenu
@@ -23,13 +23,12 @@ from nw.gui.theme import GuiIcons, GuiTheme
__all__ = [
"GuiAbout",
"GuiBuildNovel",
- "GuiDocTitleBar",
"GuiSearchBar",
- "GuiDocViewDetails",
"GuiDocEditor",
"GuiDocMerge",
"GuiDocSplit",
"GuiDocViewer",
+ "GuiDocViewDetails",
"GuiItemDetails",
"GuiItemEditor",
"GuiMainMenu",
diff --git a/nw/gui/custom.py b/nw/gui/custom.py
index 264a2c98..5c3dfbd6 100644
--- a/nw/gui/custom.py
+++ b/nw/gui/custom.py
@@ -45,7 +45,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__)
# =============================================================================================== #
-# Config FOrm Layout
+# Config Form Layout
# =============================================================================================== #
class QConfigLayout(QGridLayout):
diff --git a/nw/gui/docbars.py b/nw/gui/docbars.py
index 839ae024..079f989a 100644
--- a/nw/gui/docbars.py
+++ b/nw/gui/docbars.py
@@ -7,9 +7,6 @@
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
@@ -169,382 +166,3 @@ class GuiSearchBar(QWidget):
return True
# END Class GuiSearchBar
-
-class GuiDocTitleBar(QWidget):
-
- def __init__(self, theParent, isEditor):
- QWidget.__init__(self, theParent)
-
- logger.debug("Initialising GuiDocTitleBar ...")
-
- self.mainConf = nw.CONFIG
- self.theParent = theParent
- self.theProject = theParent.theProject
- self.theTheme = theParent.theTheme
- self.theHandle = None
- self.isEditor = isEditor
-
- # 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)
- self.buttonSize = fPx + hSp
-
- # Main Widget Settings
- self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
- self.setAutoFillBackground(True)
- self.setPalette(self.thePalette)
-
- # Title Label
- self.theTitle = QLabel()
- self.theTitle.setText("")
- self.theTitle.setIndent(0)
- self.theTitle.setMargin(0)
- self.theTitle.setContentsMargins(0, 0, 0, 0)
- self.theTitle.setAutoFillBackground(True)
- self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
- self.theTitle.setFixedHeight(fPx)
- self.theTitle.setFrameShape(QFrame.NoFrame)
- self.theTitle.setLineWidth(0)
- self.theTitle.setPalette(self.thePalette)
-
- lblFont = self.theTitle.font()
- lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
- self.theTitle.setFont(lblFont)
-
- buttonStyle = (
- "QToolButton {{border: none; background: transparent;}} "
- "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
- ).format(*self.theTheme.colText)
-
- # Buttons
- self.closeButton = QToolButton(self)
- self.closeButton.setIcon(self.theTheme.getIcon("close"))
- self.closeButton.setContentsMargins(0, 0, 0, 0)
- self.closeButton.setIconSize(QSize(fPx, fPx))
- self.closeButton.setFixedSize(fPx, fPx)
- self.closeButton.setStyleSheet(buttonStyle)
- self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
- self.closeButton.setVisible(False)
- self.closeButton.clicked.connect(self._closeDocument)
-
- if self.isEditor:
- self.minmaxButton = QToolButton(self)
- self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
- self.minmaxButton.setContentsMargins(0, 0, 0, 0)
- self.minmaxButton.setIconSize(QSize(fPx, fPx))
- self.minmaxButton.setFixedSize(fPx, fPx)
- self.minmaxButton.setStyleSheet(buttonStyle)
- self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
- self.minmaxButton.setVisible(False)
- self.minmaxButton.clicked.connect(self._minmaxDocument)
- else:
- self.refreshButton = QToolButton(self)
- self.refreshButton.setIcon(self.theTheme.getIcon("refresh"))
- self.refreshButton.setContentsMargins(0, 0, 0, 0)
- self.refreshButton.setIconSize(QSize(fPx, fPx))
- self.refreshButton.setFixedSize(fPx, fPx)
- self.refreshButton.setStyleSheet(buttonStyle)
- self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
- self.refreshButton.setVisible(False)
- self.refreshButton.clicked.connect(self._refreshDocument)
-
- # Assemble Layout
- self.outerBox = QHBoxLayout()
- self.outerBox.setSpacing(hSp)
- self.outerBox.addWidget(self.theTitle, 1)
- if self.isEditor:
- self.outerBox.addWidget(self.minmaxButton, 0)
- else:
- self.outerBox.addWidget(self.refreshButton, 0)
- self.outerBox.addWidget(self.closeButton, 0)
- self.setLayout(self.outerBox)
-
- logger.debug("GuiDocTitleBar initialisation complete")
-
- return
-
- ##
- # Setters
- ##
-
- def setTitleFromHandle(self, tHandle):
- """Sets the document title from the handle, or alternatively,
- set the whole document path.
- """
- self.theTitle.setText("")
- self.theHandle = tHandle
- if tHandle is None:
- self.closeButton.setVisible(False)
- if self.isEditor:
- self.minmaxButton.setVisible(False)
- else:
- self.refreshButton.setVisible(False)
- return False
-
- if self.mainConf.showFullPath:
- tTitle = []
- tTree = self.theProject.projTree.getItemPath(tHandle)
- for aHandle in reversed(tTree):
- nwItem = self.theProject.projTree[aHandle]
- if nwItem is not None:
- tTitle.append(nwItem.itemName)
- sSep = " %s " % nwUnicode.U_RSAQUO
- self.theTitle.setText(sSep.join(tTitle))
- else:
- nwItem = self.theProject.projTree[tHandle]
- if nwItem is None:
- return False
- self.theTitle.setText(nwItem.itemName)
-
- self.closeButton.setVisible(True)
- if self.isEditor:
- self.minmaxButton.setVisible(True)
- else:
- self.refreshButton.setVisible(True)
-
- return True
-
- ##
- # Slots
- ##
-
- def _closeDocument(self):
- """Trigger the close editor/viewer on the main window.
- """
- if self.isEditor:
- self.theParent.theParent.closeDocEditor()
- else:
- self.theParent.theParent.closeDocViewer()
- return
-
- def _minmaxDocument(self):
- """Switch on or off zen mode.
- """
- self.theParent.theParent.toggleZenMode()
- if self.theParent.theParent.isZenMode:
- self.minmaxButton.setIcon(self.theTheme.getIcon("minimise"))
- self.setContentsMargins(self.buttonSize, 0, 0, 0)
- self.closeButton.setVisible(False)
- else:
- self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
- self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
- self.closeButton.setVisible(True)
- return
-
- def _refreshDocument(self):
- """Reload the content of the document.
- """
- self.theParent.reloadText()
- return
-
- ##
- # Events
- ##
-
- def mousePressEvent(self, theEvent):
- """Capture a click on the title and ensure that the item is
- selected in the project tree.
- """
- self.theParent.setSelectedHandle(self.theHandle)
- 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/doceditor.py b/nw/gui/doceditor.py
index d3b6eb93..bd5da37f 100644
--- a/nw/gui/doceditor.py
+++ b/nw/gui/doceditor.py
@@ -8,6 +8,7 @@
File History:
Created: 2018-09-29 [0.0.1] GuiDocEditor
Created: 2019-04-22 [0.0.1] WordCounter
+ Created: 2020-04-25 [0.4.5] GuiDocEditHeader
This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen
@@ -31,18 +32,18 @@ import nw
from time import time
-from PyQt5.QtCore import Qt, QThread, QTimer, pyqtSlot
-from PyQt5.QtWidgets import (
- qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox
-)
+from PyQt5.QtCore import Qt, QSize, QThread, QTimer, pyqtSlot
from PyQt5.QtGui import (
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
QTextDocument, QCursor
)
+from PyQt5.QtWidgets import (
+ qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QWidget, QLabel,
+ QToolButton, QHBoxLayout
+)
from nw.core import NWDoc
from nw.gui.dochighlight import GuiDocHighlighter
-from nw.gui.docbars import GuiDocTitleBar
from nw.core import NWSpellSimple, countWords
from nw.constants import nwUnicode, nwDocAction
@@ -85,9 +86,7 @@ class GuiDocEditor(QTextEdit):
self.qDocument.contentsChange.connect(self._docChange)
# Document Title
- 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)
+ self.docHeader = GuiDocEditHeader(self)
# Syntax
self.hLight = GuiDocHighlighter(self.qDocument, self.theParent)
@@ -134,9 +133,6 @@ class GuiDocEditor(QTextEdit):
logger.debug("GuiDocEditor initialisation complete")
- # Connect Functions
- self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
-
return
def clearEditor(self):
@@ -158,7 +154,7 @@ class GuiDocEditor(QTextEdit):
self.hasSelection = False
self.setDocumentChanged(False)
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
return True
@@ -270,7 +266,7 @@ class GuiDocEditor(QTextEdit):
self.theHandle = tHandle
self.setReadOnly(False)
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins()
self.hLight.spellCheck = spTemp
qApp.restoreOverrideCursor()
@@ -333,11 +329,11 @@ class GuiDocEditor(QTextEdit):
else:
tM = cM
- tB = self.lineWidth()
+ tB = self.frameWidth()
tW = self.width() - 2*tB - sW
- tH = self.docTitle.height()
+ tH = self.docHeader.height()
tT = cM - tH
- self.docTitle.setGeometry(tB, tB, tW, tH)
+ self.docHeader.setGeometry(tB, tB, tW, tH)
self.setViewportMargins(0, tH, 0, 0)
docFormat = self.qDocument.rootFrame().frameFormat()
@@ -368,7 +364,7 @@ class GuiDocEditor(QTextEdit):
title bar needs updating,
"""
if tHandle == self.theHandle:
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins()
return
@@ -1105,3 +1101,158 @@ class WordCounter(QThread):
return
## END Class WordCounter
+
+class GuiDocEditHeader(QWidget):
+
+ def __init__(self, docEditor):
+ QWidget.__init__(self, docEditor)
+
+ logger.debug("Initialising GuiDocEditHeader ...")
+
+ self.mainConf = nw.CONFIG
+ self.docEditor = docEditor
+ self.theParent = docEditor.theParent
+ self.theProject = docEditor.theProject
+ self.theTheme = docEditor.theTheme
+ 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)
+ self.buttonSize = fPx + hSp
+
+ # Main Widget Settings
+ self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
+ self.setAutoFillBackground(True)
+ self.setPalette(self.thePalette)
+
+ # Title Label
+ self.theTitle = QLabel()
+ self.theTitle.setText("")
+ self.theTitle.setIndent(0)
+ self.theTitle.setMargin(0)
+ self.theTitle.setContentsMargins(0, 0, 0, 0)
+ self.theTitle.setAutoFillBackground(True)
+ self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
+ self.theTitle.setFixedHeight(fPx)
+ self.theTitle.setPalette(self.thePalette)
+
+ lblFont = self.theTitle.font()
+ lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
+ self.theTitle.setFont(lblFont)
+
+ buttonStyle = (
+ "QToolButton {{border: none; background: transparent;}} "
+ "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
+ ).format(*self.theTheme.colText)
+
+ # Buttons
+ self.minmaxButton = QToolButton(self)
+ self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
+ self.minmaxButton.setContentsMargins(0, 0, 0, 0)
+ self.minmaxButton.setIconSize(QSize(fPx, fPx))
+ self.minmaxButton.setFixedSize(fPx, fPx)
+ self.minmaxButton.setStyleSheet(buttonStyle)
+ self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.minmaxButton.setVisible(False)
+ self.minmaxButton.clicked.connect(self._minmaxDocument)
+
+ self.closeButton = QToolButton(self)
+ self.closeButton.setIcon(self.theTheme.getIcon("close"))
+ self.closeButton.setContentsMargins(0, 0, 0, 0)
+ self.closeButton.setIconSize(QSize(fPx, fPx))
+ self.closeButton.setFixedSize(fPx, fPx)
+ self.closeButton.setStyleSheet(buttonStyle)
+ self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.closeButton.setVisible(False)
+ self.closeButton.clicked.connect(self._closeDocument)
+
+ # Assemble Layout
+ self.outerBox = QHBoxLayout()
+ self.outerBox.setSpacing(hSp)
+ self.outerBox.addWidget(self.theTitle, 1)
+ self.outerBox.addWidget(self.minmaxButton, 0)
+ self.outerBox.addWidget(self.closeButton, 0)
+ self.setLayout(self.outerBox)
+
+ logger.debug("GuiDocEditHeader initialisation complete")
+
+ return
+
+ ##
+ # Setters
+ ##
+
+ def setTitleFromHandle(self, tHandle):
+ """Sets the document title from the handle, or alternatively,
+ set the whole document path.
+ """
+ self.theHandle = tHandle
+ if tHandle is None:
+ self.theTitle.setText("")
+ self.closeButton.setVisible(False)
+ self.minmaxButton.setVisible(False)
+ return True
+
+ if self.mainConf.showFullPath:
+ tTitle = []
+ tTree = self.theProject.projTree.getItemPath(tHandle)
+ for aHandle in reversed(tTree):
+ nwItem = self.theProject.projTree[aHandle]
+ if nwItem is not None:
+ tTitle.append(nwItem.itemName)
+ sSep = " %s " % nwUnicode.U_RSAQUO
+ self.theTitle.setText(sSep.join(tTitle))
+ else:
+ nwItem = self.theProject.projTree[tHandle]
+ if nwItem is None:
+ return False
+ self.theTitle.setText(nwItem.itemName)
+
+ self.closeButton.setVisible(True)
+ self.minmaxButton.setVisible(True)
+
+ return True
+
+ ##
+ # Slots
+ ##
+
+ def _closeDocument(self):
+ """Trigger the close editor/viewer on the main window.
+ """
+ self.theParent.closeDocEditor()
+ self.closeButton.setVisible(False)
+ self.minmaxButton.setVisible(False)
+ return
+
+ def _minmaxDocument(self):
+ """Switch on or off zen mode.
+ """
+ self.theParent.toggleZenMode()
+ if self.theParent.isZenMode:
+ self.minmaxButton.setIcon(self.theTheme.getIcon("minimise"))
+ self.setContentsMargins(self.buttonSize, 0, 0, 0)
+ self.closeButton.setVisible(False)
+ else:
+ self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
+ self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
+ self.closeButton.setVisible(True)
+ return
+
+ ##
+ # Events
+ ##
+
+ def mousePressEvent(self, theEvent):
+ """Capture a click on the title and ensure that the item is
+ selected in the project tree.
+ """
+ self.theParent.treeView.setSelectedHandle(self.theHandle)
+ return
+
+# END Class GuiDocEditHeader
diff --git a/nw/gui/dochighlight.py b/nw/gui/dochighlight.py
index cda6ac03..afd5a77c 100644
--- a/nw/gui/dochighlight.py
+++ b/nw/gui/dochighlight.py
@@ -42,7 +42,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
def __init__(self, theDoc, theParent):
QSyntaxHighlighter.__init__(self, theDoc)
- logger.debug("Initialising DocHighlighter ...")
+ logger.debug("Initialising GuiDocHighlighter ...")
self.mainConf = nw.CONFIG
self.theDoc = theDoc
self.theParent = theParent
@@ -70,7 +70,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.initHighlighter()
- logger.debug("DocHighlighter initialisation complete")
+ logger.debug("GuiDocHighlighter initialisation complete")
return
diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py
index 0648111b..a2884dab 100644
--- a/nw/gui/docviewer.py
+++ b/nw/gui/docviewer.py
@@ -6,7 +6,10 @@
Class holding the document html viewer
File History:
- Created: 2019-05-10 [0.0.1]
+ Created: 2019-05-10 [0.0.1] GuiDocViewer
+ Created: 2019-10-31 [0.3.2] GuiDocViewDetails
+ Created: 2020-04-25 [0.4.5] GuiDocViewHeader
+ Created: 2020-06-09 [0.8.0] GuiDocViewFooter
This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen
@@ -28,13 +31,16 @@
import logging
import nw
-from PyQt5.QtCore import Qt, QUrl
-from PyQt5.QtWidgets import QTextBrowser
-from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
+from PyQt5.QtCore import Qt, QUrl, QSize
+from PyQt5.QtGui import (
+ QTextOption, QFont, QPalette, QColor, QTextCursor, QIcon
+)
+from PyQt5.QtWidgets import (
+ QTextBrowser, QWidget, QScrollArea, QLabel, QHBoxLayout, QToolButton
+)
from nw.core import ToHtml
-from nw.constants import nwAlert, nwItemType, nwDocAction
-from nw.gui.docbars import GuiDocTitleBar, GuiDocViewFooter
+from nw.constants import nwAlert, nwItemType, nwDocAction, nwUnicode
logger = logging.getLogger(__name__)
@@ -57,8 +63,8 @@ class GuiDocViewer(QTextBrowser):
self.setOpenExternalLinks(False)
self.initViewer()
- # Document Title and Footer
- self.docTitle = GuiDocTitleBar(self, isEditor=False)
+ # Document Header and Footer
+ self.docHeader = GuiDocViewHeader(self)
self.docFooter = GuiDocViewFooter(self)
self.stickyRef = False
@@ -72,9 +78,6 @@ class GuiDocViewer(QTextBrowser):
logger.debug("GuiDocViewer initialisation complete")
- # Connect Functions
- self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
-
return
def clearViewer(self):
@@ -83,7 +86,7 @@ class GuiDocViewer(QTextBrowser):
self.clear()
self.setSearchPaths([""])
self.theHandle = None
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
return True
def initViewer(self):
@@ -156,7 +159,7 @@ class GuiDocViewer(QTextBrowser):
self.verticalScrollBar().setValue(sPos)
self.theHandle = tHandle
self.theProject.setLastViewed(tHandle)
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins()
# Make sure the main GUI knows we changed the content
@@ -185,7 +188,10 @@ class GuiDocViewer(QTextBrowser):
) % theTag, nwAlert.ERROR)
return
else:
- self.loadText(tHandle)
+ # Let the parent handle the opening as it also ensures that
+ # the doc view panel is visible in case this request comes
+ # from outside this class.
+ self.theParent.viewDocument(tHandle)
self.navigateTo("#head_%s:%s" % (tHandle, sTitle))
return True
@@ -230,14 +236,14 @@ class GuiDocViewer(QTextBrowser):
else:
sW = 0
- tB = self.lineWidth()
+ tB = self.frameWidth()
tW = self.width() - 2*tB - sW
- tH = self.docTitle.height()
+ tH = self.docHeader.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.docHeader.setGeometry(tB, tB, tW, tH)
self.docFooter.setGeometry(tB, fY, tW, fH)
self.setViewportMargins(0, tH, 0, fH)
@@ -256,7 +262,7 @@ class GuiDocViewer(QTextBrowser):
title bar needs updating,
"""
if tHandle == self.theHandle:
- self.docTitle.setTitleFromHandle(self.theHandle)
+ self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins()
return
@@ -387,3 +393,360 @@ class GuiDocViewer(QTextBrowser):
return True
# END Class GuiDocViewer
+
+# =============================================================================================== #
+# The Embedded Document Header
+# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
+# =============================================================================================== #
+
+class GuiDocViewHeader(QWidget):
+
+ def __init__(self, docViewer):
+ QWidget.__init__(self, docViewer)
+
+ logger.debug("Initialising GuiDocViewHeader ...")
+
+ self.mainConf = nw.CONFIG
+ self.docViewer = docViewer
+ self.theParent = docViewer.theParent
+ self.theProject = docViewer.theProject
+ self.theTheme = docViewer.theTheme
+ 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)
+ self.buttonSize = fPx + hSp
+
+ # Main Widget Settings
+ self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
+ self.setAutoFillBackground(True)
+ self.setPalette(self.thePalette)
+
+ # Title Label
+ self.theTitle = QLabel()
+ self.theTitle.setText("")
+ self.theTitle.setIndent(0)
+ self.theTitle.setMargin(0)
+ self.theTitle.setContentsMargins(0, 0, 0, 0)
+ self.theTitle.setAutoFillBackground(True)
+ self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
+ self.theTitle.setFixedHeight(fPx)
+ self.theTitle.setPalette(self.thePalette)
+
+ lblFont = self.theTitle.font()
+ lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
+ self.theTitle.setFont(lblFont)
+
+ buttonStyle = (
+ "QToolButton {{border: none; background: transparent;}} "
+ "QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
+ ).format(*self.theTheme.colText)
+
+ # Buttons
+ self.closeButton = QToolButton(self)
+ self.closeButton.setIcon(self.theTheme.getIcon("close"))
+ self.closeButton.setContentsMargins(0, 0, 0, 0)
+ self.closeButton.setIconSize(QSize(fPx, fPx))
+ self.closeButton.setFixedSize(fPx, fPx)
+ self.closeButton.setStyleSheet(buttonStyle)
+ self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.closeButton.setVisible(False)
+ self.closeButton.clicked.connect(self._closeDocument)
+
+ self.refreshButton = QToolButton(self)
+ self.refreshButton.setIcon(self.theTheme.getIcon("refresh"))
+ self.refreshButton.setContentsMargins(0, 0, 0, 0)
+ self.refreshButton.setIconSize(QSize(fPx, fPx))
+ self.refreshButton.setFixedSize(fPx, fPx)
+ self.refreshButton.setStyleSheet(buttonStyle)
+ self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.refreshButton.setVisible(False)
+ self.refreshButton.clicked.connect(self._refreshDocument)
+
+ # Assemble Layout
+ self.outerBox = QHBoxLayout()
+ self.outerBox.setSpacing(hSp)
+ self.outerBox.addWidget(self.theTitle, 1)
+ self.outerBox.addWidget(self.refreshButton, 0)
+ self.outerBox.addWidget(self.closeButton, 0)
+ self.setLayout(self.outerBox)
+
+ logger.debug("GuiDocViewHeader initialisation complete")
+
+ return
+
+ ##
+ # Setters
+ ##
+
+ def setTitleFromHandle(self, tHandle):
+ """Sets the document title from the handle, or alternatively,
+ set the whole document path.
+ """
+ self.theHandle = tHandle
+ if tHandle is None:
+ self.theTitle.setText("")
+ self.closeButton.setVisible(False)
+ self.refreshButton.setVisible(False)
+ return True
+
+ if self.mainConf.showFullPath:
+ tTitle = []
+ tTree = self.theProject.projTree.getItemPath(tHandle)
+ for aHandle in reversed(tTree):
+ nwItem = self.theProject.projTree[aHandle]
+ if nwItem is not None:
+ tTitle.append(nwItem.itemName)
+ sSep = " %s " % nwUnicode.U_RSAQUO
+ self.theTitle.setText(sSep.join(tTitle))
+ else:
+ nwItem = self.theProject.projTree[tHandle]
+ if nwItem is None:
+ return False
+ self.theTitle.setText(nwItem.itemName)
+
+ self.closeButton.setVisible(True)
+ self.refreshButton.setVisible(True)
+
+ return True
+
+ ##
+ # Slots
+ ##
+
+ def _closeDocument(self):
+ """Trigger the close editor/viewer on the main window.
+ """
+ self.theParent.closeDocViewer()
+ return
+
+ def _refreshDocument(self):
+ """Reload the content of the document.
+ """
+ self.docViewer.reloadText()
+ return
+
+ ##
+ # Events
+ ##
+
+ def mousePressEvent(self, theEvent):
+ """Capture a click on the title and ensure that the item is
+ selected in the project tree.
+ """
+ self.theParent.treeView.setSelectedHandle(self.theHandle)
+ return
+
+# END Class GuiDocViewHeader
+
+# =============================================================================================== #
+# The Embedded Document Footer
+# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
+# =============================================================================================== #
+
+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)
+ bSp = self.mainConf.pxInt(2)
+ hSp = self.mainConf.pxInt(8)
+
+ # 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(bSp)
+ self.outerBox.addWidget(self.showHide, 0)
+ self.outerBox.addWidget(self.lblRefs, 0)
+ self.outerBox.addSpacing(hSp)
+ 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
+
+# =============================================================================================== #
+# The Document Back-Reference Panel
+# Placed in a separate QSplitter position in the main GUI window
+# =============================================================================================== #
+
+class GuiDocViewDetails(QScrollArea):
+
+ def __init__(self, theParent):
+ QScrollArea.__init__(self, theParent)
+
+ logger.debug("Initialising GuiDocViewDetails ...")
+ self.mainConf = nw.CONFIG
+ self.theParent = theParent
+ self.theProject = theParent.theProject
+ self.theTheme = theParent.theTheme
+ self.currHandle = None
+
+ self.refList = QLabel("")
+ 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("GuiDocViewDetails 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/outlinedetails.py b/nw/gui/outlinedetails.py
index 9a010559..5e197449 100644
--- a/nw/gui/outlinedetails.py
+++ b/nw/gui/outlinedetails.py
@@ -277,7 +277,6 @@ class GuiOutlineDetails(QScrollArea):
theBits = theLink.split("=")
if len(theBits) == 2:
self.theParent.docViewer.loadFromTag(theBits[1])
- self.theParent.tabWidget.setCurrentWidget(self.theParent.splitView)
return
##
diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py
index b7b9029c..02e850ad 100644
--- a/nw/gui/projtree.py
+++ b/nw/gui/projtree.py
@@ -525,9 +525,13 @@ class GuiProjectTree(QTreeWidget):
always make sure items with a parent have had their parent item
sent first.
"""
+ logger.debug("Building project tree ...")
self.clear()
+ iCount = 0
for nwItem in self.theProject.getProjectItems():
+ iCount += 1
self._addTreeItem(nwItem)
+ logger.debug("%d items added to project tree" % iCount)
return True
def getSelectedHandle(self):
diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py
index a7fbc342..a40e4022 100644
--- a/nw/gui/statusbar.py
+++ b/nw/gui/statusbar.py
@@ -44,7 +44,7 @@ class GuiMainStatus(QStatusBar):
def __init__(self, theParent):
QStatusBar.__init__(self, theParent)
- logger.debug("Initialising MainStatus ...")
+ logger.debug("Initialising GuiMainStatus ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
@@ -123,7 +123,7 @@ class GuiMainStatus(QStatusBar):
self.sessionTimer.timeout.connect(self._updateTime)
self.sessionTimer.start()
- logger.debug("MainStatus initialisation complete")
+ logger.debug("GuiMainStatus initialisation complete")
self.clearStatus()
diff --git a/nw/gui/theme.py b/nw/gui/theme.py
index 78b2b44d..98c9a7b9 100644
--- a/nw/gui/theme.py
+++ b/nw/gui/theme.py
@@ -750,11 +750,11 @@ class GuiIcons:
self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey
)
if path.isfile(fbackIcon):
- logger.verbose("Loading icon '%s' from fallback theme" % iconKey)
+ logger.verbose("Loading icon '%s' from fallback theme (dark mode)" % iconKey)
return QIcon(fbackIcon)
fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey)
if path.isfile(fbackIcon):
- logger.verbose("Loading icon '%s' from fallback theme" % iconKey)
+ logger.verbose("Loading icon '%s' from fallback theme (light mode)" % iconKey)
return QIcon(fbackIcon)
# Give up and return an empty icon
diff --git a/nw/guimain.py b/nw/guimain.py
index e34ff448..576cd990 100644
--- a/nw/guimain.py
+++ b/nw/guimain.py
@@ -55,7 +55,6 @@ class GuiMain(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
- logger.info("Starting %s" % nw.__package__)
logger.debug("Initialising GUI ...")
self.mainConf = nw.CONFIG
@@ -232,6 +231,8 @@ class GuiMain(QMainWindow):
else:
self.manageProjects()
+ logger.debug("%s is ready ..." % nw.__package__)
+
return
def clearGUI(self):
@@ -435,6 +436,8 @@ class GuiMain(QMainWindow):
if self.theIndex.indexBroken:
self.rebuildIndex()
+ logger.debug("Project load complete")
+
return True
def saveProject(self, autoSave=False):