@@ -18,6 +18,7 @@ sample/**/wordlist.txt
|
|||||||
sample/**/sessionInfo.log
|
sample/**/sessionInfo.log
|
||||||
sample/**/*.bak
|
sample/**/*.bak
|
||||||
sample/**/*.json
|
sample/**/*.json
|
||||||
|
sample/**/*.lock
|
||||||
|
|
||||||
# PyTest
|
# PyTest
|
||||||
tests/temp
|
tests/temp
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ class Config:
|
|||||||
self.showTabsNSpaces = False
|
self.showTabsNSpaces = False
|
||||||
self.showLineEndings = False
|
self.showLineEndings = False
|
||||||
self.bigDocLimit = 800
|
self.bigDocLimit = 800
|
||||||
|
self.showFullPath = True
|
||||||
|
|
||||||
self.fmtApostrophe = nwUnicode.U_RSQUO
|
self.fmtApostrophe = nwUnicode.U_RSQUO
|
||||||
self.fmtSingleQuotes = [nwUnicode.U_LSQUO,nwUnicode.U_RSQUO]
|
self.fmtSingleQuotes = [nwUnicode.U_LSQUO,nwUnicode.U_RSQUO]
|
||||||
@@ -398,6 +399,9 @@ class Config:
|
|||||||
self.bigDocLimit = self._parseLine(
|
self.bigDocLimit = self._parseLine(
|
||||||
cnfParse, cnfSec, "bigdoclimit", self.CNF_INT, self.bigDocLimit
|
cnfParse, cnfSec, "bigdoclimit", self.CNF_INT, self.bigDocLimit
|
||||||
)
|
)
|
||||||
|
self.showFullPath = self._parseLine(
|
||||||
|
cnfParse, cnfSec, "showfullpath", self.CNF_BOOL, self.showFullPath
|
||||||
|
)
|
||||||
|
|
||||||
## Backup
|
## Backup
|
||||||
cnfSec = "Backup"
|
cnfSec = "Backup"
|
||||||
@@ -486,6 +490,7 @@ class Config:
|
|||||||
cnfParse.set(cnfSec,"showtabsnspaces", str(self.showTabsNSpaces))
|
cnfParse.set(cnfSec,"showtabsnspaces", str(self.showTabsNSpaces))
|
||||||
cnfParse.set(cnfSec,"showlineendings", str(self.showLineEndings))
|
cnfParse.set(cnfSec,"showlineendings", str(self.showLineEndings))
|
||||||
cnfParse.set(cnfSec,"bigdoclimit", str(self.bigDocLimit))
|
cnfParse.set(cnfSec,"bigdoclimit", str(self.bigDocLimit))
|
||||||
|
cnfParse.set(cnfSec,"showfullpath", str(self.showFullPath))
|
||||||
|
|
||||||
## Backup
|
## Backup
|
||||||
cnfSec = "Backup"
|
cnfSec = "Backup"
|
||||||
|
|||||||
@@ -234,6 +234,12 @@ class nwUnicode:
|
|||||||
U_NBSP = "\u00a0" # Non-breaking space
|
U_NBSP = "\u00a0" # Non-breaking space
|
||||||
U_PARA = "\u2029" # Paragraph separator
|
U_PARA = "\u2029" # Paragraph separator
|
||||||
|
|
||||||
|
## Arrows
|
||||||
|
U_UTRI = "\u2bc5" # Up-pointing triangle
|
||||||
|
U_DTRI = "\u2bc6" # Down-pointing triangle
|
||||||
|
U_LTRI = "\u2bc7" # Left-pointing triangle
|
||||||
|
U_RTRI = "\u2bc8" # Right-pointing triangle
|
||||||
|
|
||||||
# HTML Equivalents
|
# HTML Equivalents
|
||||||
|
|
||||||
## Quotes
|
## Quotes
|
||||||
@@ -265,4 +271,10 @@ class nwUnicode:
|
|||||||
## Other
|
## Other
|
||||||
H_NBSP = " "
|
H_NBSP = " "
|
||||||
|
|
||||||
|
## Arrows
|
||||||
|
H_UTRI = "⯅"
|
||||||
|
H_DTRI = "⯆"
|
||||||
|
H_LTRI = "⯇"
|
||||||
|
H_RTRI = "⯈"
|
||||||
|
|
||||||
# END Class nwUnicode
|
# END Class nwUnicode
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from nw.gui.dialogs.sessionlog import GuiSessionLogView
|
|||||||
# GUI Elements
|
# GUI Elements
|
||||||
from nw.gui.elements.docdetails import GuiDocDetails
|
from nw.gui.elements.docdetails import GuiDocDetails
|
||||||
from nw.gui.elements.doceditor import GuiDocEditor
|
from nw.gui.elements.doceditor import GuiDocEditor
|
||||||
|
from nw.gui.elements.doctitlebar import GuiDocTitleBar
|
||||||
from nw.gui.elements.doctree import GuiDocTree
|
from nw.gui.elements.doctree import GuiDocTree
|
||||||
from nw.gui.elements.docviewer import GuiDocViewer
|
from nw.gui.elements.docviewer import GuiDocViewer
|
||||||
from nw.gui.elements.noticebar import GuiNoticeBar
|
from nw.gui.elements.noticebar import GuiNoticeBar
|
||||||
@@ -45,6 +46,7 @@ __all__ = [
|
|||||||
"GuiSessionLogView",
|
"GuiSessionLogView",
|
||||||
"GuiDocDetails",
|
"GuiDocDetails",
|
||||||
"GuiDocEditor",
|
"GuiDocEditor",
|
||||||
|
"GuiDocTitleBar",
|
||||||
"GuiDocTree",
|
"GuiDocTree",
|
||||||
"GuiDocViewer",
|
"GuiDocViewer",
|
||||||
"GuiNoticeBar",
|
"GuiNoticeBar",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from nw.gui.elements.docdetails import GuiDocDetails
|
from nw.gui.elements.docdetails import GuiDocDetails
|
||||||
from nw.gui.elements.doceditor import GuiDocEditor
|
from nw.gui.elements.doceditor import GuiDocEditor
|
||||||
|
from nw.gui.elements.doctitlebar import GuiDocTitleBar
|
||||||
from nw.gui.elements.doctree import GuiDocTree
|
from nw.gui.elements.doctree import GuiDocTree
|
||||||
from nw.gui.elements.docviewer import GuiDocViewer
|
from nw.gui.elements.docviewer import GuiDocViewer
|
||||||
from nw.gui.elements.noticebar import GuiNoticeBar
|
from nw.gui.elements.noticebar import GuiNoticeBar
|
||||||
@@ -12,6 +13,7 @@ from nw.gui.elements.viewdetails import GuiDocViewDetails
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
"GuiDocDetails",
|
"GuiDocDetails",
|
||||||
"GuiDocEditor",
|
"GuiDocEditor",
|
||||||
|
"GuiDocTitleBar",
|
||||||
"GuiDocTree",
|
"GuiDocTree",
|
||||||
"GuiDocViewer",
|
"GuiDocViewer",
|
||||||
"GuiNoticeBar",
|
"GuiNoticeBar",
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ from time import time
|
|||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer
|
from PyQt5.QtCore import Qt, QTimer
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox
|
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QLabel
|
||||||
)
|
)
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
|
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
|
||||||
@@ -41,6 +41,7 @@ from PyQt5.QtGui import (
|
|||||||
|
|
||||||
from nw.project import NWDoc
|
from nw.project import NWDoc
|
||||||
from nw.gui.tools import GuiDocHighlighter, WordCounter
|
from nw.gui.tools import GuiDocHighlighter, WordCounter
|
||||||
|
from nw.gui.elements.doctitlebar import GuiDocTitleBar
|
||||||
from nw.tools import NWSpellSimple
|
from nw.tools import NWSpellSimple
|
||||||
from nw.constants import nwUnicode, nwDocAction
|
from nw.constants import nwUnicode, nwDocAction
|
||||||
|
|
||||||
@@ -82,6 +83,10 @@ class GuiDocEditor(QTextEdit):
|
|||||||
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
|
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
|
||||||
self.qDocument.contentsChange.connect(self._docChange)
|
self.qDocument.contentsChange.connect(self._docChange)
|
||||||
|
|
||||||
|
# Document Title
|
||||||
|
self.docTitle = GuiDocTitleBar(self, self.theProject)
|
||||||
|
self.docTitle.setGeometry(0,0,self.docTitle.width(),self.docTitle.height())
|
||||||
|
|
||||||
# Syntax
|
# Syntax
|
||||||
self.hLight = GuiDocHighlighter(self.qDocument, self.theParent)
|
self.hLight = GuiDocHighlighter(self.qDocument, self.theParent)
|
||||||
|
|
||||||
@@ -127,11 +132,14 @@ class GuiDocEditor(QTextEdit):
|
|||||||
|
|
||||||
logger.debug("DocEditor initialisation complete")
|
logger.debug("DocEditor initialisation complete")
|
||||||
|
|
||||||
|
# Connect Functions
|
||||||
|
self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def clearEditor(self):
|
def clearEditor(self):
|
||||||
"""Clear the current document and reset all document related
|
"""Clear the current document and reset all document related
|
||||||
flags and counters.
|
flags and counters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.nwDocument.clearDocument()
|
self.nwDocument.clearDocument()
|
||||||
@@ -150,6 +158,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
|
|
||||||
self.setDocumentChanged(False)
|
self.setDocumentChanged(False)
|
||||||
self.theParent.noticeBar.hideNote()
|
self.theParent.noticeBar.hideNote()
|
||||||
|
self.docTitle.setTitleFromHandle(self.theHandle)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -264,6 +273,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
else:
|
else:
|
||||||
self.theParent.noticeBar.showNote("This document is read only.")
|
self.theParent.noticeBar.showNote("This document is read only.")
|
||||||
|
|
||||||
|
self.docTitle.setTitleFromHandle(self.theHandle)
|
||||||
self.hLight.spellCheck = spTemp
|
self.hLight.spellCheck = spTemp
|
||||||
qApp.restoreOverrideCursor()
|
qApp.restoreOverrideCursor()
|
||||||
|
|
||||||
@@ -319,9 +329,16 @@ class GuiDocEditor(QTextEdit):
|
|||||||
else:
|
else:
|
||||||
tM = self.mainConf.textMargin
|
tM = self.mainConf.textMargin
|
||||||
|
|
||||||
|
tB = self.lineWidth()
|
||||||
|
tW = self.width() - 2*tB
|
||||||
|
tH = self.docTitle.height()
|
||||||
|
self.docTitle.setGeometry(tB, tB, tW, tH)
|
||||||
|
|
||||||
docFormat = self.qDocument.rootFrame().frameFormat()
|
docFormat = self.qDocument.rootFrame().frameFormat()
|
||||||
docFormat.setLeftMargin(tM)
|
docFormat.setLeftMargin(tM)
|
||||||
docFormat.setRightMargin(tM)
|
docFormat.setRightMargin(tM)
|
||||||
|
if docFormat.topMargin() < tH:
|
||||||
|
docFormat.setTopMargin(tH + 2)
|
||||||
|
|
||||||
# Updating root frame triggers a QTextDocument->contentsChange
|
# Updating root frame triggers a QTextDocument->contentsChange
|
||||||
# signal, which we do not want as it re-runs the syntax
|
# signal, which we do not want as it re-runs the syntax
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""novelWriter GUI Document Title Bar
|
||||||
|
|
||||||
|
novelWriter – GUI Document Title Bar
|
||||||
|
======================================
|
||||||
|
Class holding the document title bar class
|
||||||
|
|
||||||
|
File History:
|
||||||
|
Created: 2020-04-25 [0.4.5]
|
||||||
|
|
||||||
|
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 https://www.gnu.org/licenses/.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import nw
|
||||||
|
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
|
from PyQt5.QtGui import QPalette, QColor
|
||||||
|
from PyQt5.QtWidgets import QLabel, QFrame, QStyle
|
||||||
|
|
||||||
|
from nw.constants import nwUnicode
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class GuiDocTitleBar(QLabel):
|
||||||
|
|
||||||
|
def __init__(self, theParent, theProject):
|
||||||
|
QLabel.__init__(self, theParent)
|
||||||
|
|
||||||
|
logger.debug("Initialising DocTitleBar ...")
|
||||||
|
|
||||||
|
self.mainConf = nw.CONFIG
|
||||||
|
self.theParent = theParent
|
||||||
|
self.theProject = theProject
|
||||||
|
self.theTheme = theParent.theTheme
|
||||||
|
self.theHandle = None
|
||||||
|
|
||||||
|
self.setText("")
|
||||||
|
self.setIndent(0)
|
||||||
|
self.setMargin(0)
|
||||||
|
self.setContentsMargins(0,0,0,0)
|
||||||
|
self.setAutoFillBackground(True)
|
||||||
|
self.setAlignment(Qt.AlignCenter)
|
||||||
|
self.setWordWrap(True)
|
||||||
|
self.setFrameShape(QFrame.NoFrame)
|
||||||
|
self.setLineWidth(0)
|
||||||
|
lblPalette = self.palette()
|
||||||
|
lblPalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
|
||||||
|
lblPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
|
||||||
|
self.setPalette(lblPalette)
|
||||||
|
|
||||||
|
lblFont = self.font()
|
||||||
|
lblFont.setPointSizeF(0.9*self.theTheme.defFontSize)
|
||||||
|
self.setFont(lblFont)
|
||||||
|
|
||||||
|
logger.debug("DocTitleBar initialisation complete")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Setters
|
||||||
|
##
|
||||||
|
|
||||||
|
def setTitleFromHandle(self, tHandle):
|
||||||
|
"""Sets the document title from the handle, or alternatively,
|
||||||
|
set the whole document path.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.setText("")
|
||||||
|
self.theHandle = tHandle
|
||||||
|
if tHandle is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.mainConf.showFullPath:
|
||||||
|
tTitle = []
|
||||||
|
tTree = self.theProject.getItemPath(tHandle)
|
||||||
|
for aHandle in reversed(tTree):
|
||||||
|
nwItem = self.theProject.getItem(aHandle)
|
||||||
|
if nwItem is not None:
|
||||||
|
tTitle.append(nwItem.itemName)
|
||||||
|
sSep = " %s " % nwUnicode.U_RTRI
|
||||||
|
self.setText(sSep.join(tTitle))
|
||||||
|
else:
|
||||||
|
nwItem = self.theProject.getItem(tHandle)
|
||||||
|
if nwItem is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.setText(nwItem.itemName)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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
|
||||||
@@ -457,6 +457,9 @@ class GuiDocTree(QTreeWidget):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def getSelectedHandle(self):
|
def getSelectedHandle(self):
|
||||||
|
"""Get the currently selected handle. If multiple items are
|
||||||
|
selected, return the first.
|
||||||
|
"""
|
||||||
selItem = self.selectedItems()
|
selItem = self.selectedItems()
|
||||||
if len(selItem) == 0:
|
if len(selItem) == 0:
|
||||||
return None
|
return None
|
||||||
@@ -465,6 +468,8 @@ class GuiDocTree(QTreeWidget):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def getSelectedHandles(self):
|
def getSelectedHandles(self):
|
||||||
|
"""Return a list of all currently selected item handles.
|
||||||
|
"""
|
||||||
selItems = self.selectedItems()
|
selItems = self.selectedItems()
|
||||||
selHandles = []
|
selHandles = []
|
||||||
for n in range(len(selItems)):
|
for n in range(len(selItems)):
|
||||||
@@ -472,6 +477,15 @@ class GuiDocTree(QTreeWidget):
|
|||||||
selHandles.append(selItems[n].text(self.C_HANDLE))
|
selHandles.append(selItems[n].text(self.C_HANDLE))
|
||||||
return selHandles
|
return selHandles
|
||||||
|
|
||||||
|
def setSelectedHandle(self, tHandle):
|
||||||
|
"""Set a specific handle as the selected item.
|
||||||
|
"""
|
||||||
|
if tHandle in self.theMap:
|
||||||
|
self.clearSelection()
|
||||||
|
self.theMap[tHandle].setSelected(True)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor
|
|||||||
|
|
||||||
from nw.convert import ToHtml
|
from nw.convert import ToHtml
|
||||||
from nw.constants import nwAlert, nwItemType, nwDocAction
|
from nw.constants import nwAlert, nwItemType, nwDocAction
|
||||||
|
from nw.gui.elements.doctitlebar import GuiDocTitleBar
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -56,6 +57,10 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
self.setOpenExternalLinks(False)
|
self.setOpenExternalLinks(False)
|
||||||
self.initViewer()
|
self.initViewer()
|
||||||
|
|
||||||
|
# Document Title
|
||||||
|
self.docTitle = GuiDocTitleBar(self, self.theProject)
|
||||||
|
self.docTitle.setGeometry(0,0,self.docTitle.width(),self.docTitle.height())
|
||||||
|
|
||||||
theOpt = QTextOption()
|
theOpt = QTextOption()
|
||||||
if self.mainConf.doJustify:
|
if self.mainConf.doJustify:
|
||||||
theOpt.setAlignment(Qt.AlignJustify)
|
theOpt.setAlignment(Qt.AlignJustify)
|
||||||
@@ -66,11 +71,18 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
|
|
||||||
logger.debug("DocViewer initialisation complete")
|
logger.debug("DocViewer initialisation complete")
|
||||||
|
|
||||||
|
# Connect Functions
|
||||||
|
self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def clearViewer(self):
|
def clearViewer(self):
|
||||||
|
"""Clear the content of the document and reset key variables.
|
||||||
|
"""
|
||||||
self.clear()
|
self.clear()
|
||||||
self.setSearchPaths([""])
|
self.setSearchPaths([""])
|
||||||
|
self.theHandle = None
|
||||||
|
self.docTitle.setTitleFromHandle(self.theHandle)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def initViewer(self):
|
def initViewer(self):
|
||||||
@@ -108,6 +120,8 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def loadText(self, tHandle):
|
def loadText(self, tHandle):
|
||||||
|
"""Load text into the viewer from an item handle.
|
||||||
|
"""
|
||||||
|
|
||||||
tItem = self.theProject.getItem(tHandle)
|
tItem = self.theProject.getItem(tHandle)
|
||||||
if tItem is None:
|
if tItem is None:
|
||||||
@@ -131,7 +145,9 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
self.verticalScrollBar().setValue(sPos)
|
self.verticalScrollBar().setValue(sPos)
|
||||||
self.theHandle = tHandle
|
self.theHandle = tHandle
|
||||||
self.theProject.setLastViewed(tHandle)
|
self.theProject.setLastViewed(tHandle)
|
||||||
|
self.docTitle.setTitleFromHandle(self.theHandle)
|
||||||
|
|
||||||
|
# Make sure the main GUI knows we changed the content
|
||||||
self.theParent.viewMeta.refreshReferences(tHandle)
|
self.theParent.viewMeta.refreshReferences(tHandle)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -176,6 +192,26 @@ class GuiDocViewer(QTextBrowser):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Events
|
||||||
|
##
|
||||||
|
|
||||||
|
def resizeEvent(self, theEvent):
|
||||||
|
"""Make sure the document title is the same width as the window.
|
||||||
|
"""
|
||||||
|
QTextBrowser.resizeEvent(self, theEvent)
|
||||||
|
|
||||||
|
tB = self.lineWidth()
|
||||||
|
tW = self.width() - 2*tB
|
||||||
|
tH = self.docTitle.height()
|
||||||
|
self.docTitle.setGeometry(tB, tB, tW, tH)
|
||||||
|
|
||||||
|
docFormat = self.qDocument.rootFrame().frameFormat()
|
||||||
|
if docFormat.topMargin() < tH:
|
||||||
|
docFormat.setTopMargin(tH + 2)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class GuiNoticeBar(QFrame):
|
|||||||
self.mainBox = QHBoxLayout(self)
|
self.mainBox = QHBoxLayout(self)
|
||||||
self.mainBox.setContentsMargins(8,2,2,2)
|
self.mainBox.setContentsMargins(8,2,2,2)
|
||||||
|
|
||||||
self.noteLabel = QLabel("Hi there!")
|
self.noteLabel = QLabel("")
|
||||||
|
|
||||||
self.closeButton = QPushButton(self.theTheme.getIcon("close"),"")
|
self.closeButton = QPushButton(self.theTheme.getIcon("close"),"")
|
||||||
self.closeButton.clicked.connect(self.hideNote)
|
self.closeButton.clicked.connect(self.hideNote)
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ class GuiTheme:
|
|||||||
self.getPixmap = self.theIcons.getPixmap
|
self.getPixmap = self.theIcons.getPixmap
|
||||||
self.loadDecoration = self.theIcons.loadDecoration
|
self.loadDecoration = self.theIcons.loadDecoration
|
||||||
|
|
||||||
|
# Extract Other Info
|
||||||
|
self.defFont = qApp.font()
|
||||||
|
self.defFontSize = self.defFont.pointSizeF()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
+26
-2
@@ -65,6 +65,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.hasProject = False
|
self.hasProject = False
|
||||||
self.isZenMode = False
|
self.isZenMode = False
|
||||||
|
|
||||||
|
# Some runtime info useful for debugging
|
||||||
logger.info("OS: %s" % self.mainConf.osType)
|
logger.info("OS: %s" % self.mainConf.osType)
|
||||||
logger.info("Kernel: %s" % self.mainConf.kernelVer)
|
logger.info("Kernel: %s" % self.mainConf.kernelVer)
|
||||||
logger.info("Host: %s" % self.mainConf.hostName)
|
logger.info("Host: %s" % self.mainConf.hostName)
|
||||||
@@ -78,19 +79,23 @@ class GuiMain(QMainWindow):
|
|||||||
self.mainConf.verPyString, self.mainConf.verPyHexVal)
|
self.mainConf.verPyString, self.mainConf.verPyHexVal)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Prepare main window
|
||||||
self.resize(*self.mainConf.winGeometry)
|
self.resize(*self.mainConf.winGeometry)
|
||||||
self._setWindowTitle()
|
self._setWindowTitle()
|
||||||
self.setWindowIcon(QIcon(self.mainConf.appIcon))
|
self.setWindowIcon(QIcon(self.mainConf.appIcon))
|
||||||
|
|
||||||
|
# Build the GUI
|
||||||
|
################
|
||||||
|
|
||||||
# Main GUI Elements
|
# Main GUI Elements
|
||||||
self.statusBar = GuiMainStatus(self)
|
self.statusBar = GuiMainStatus(self)
|
||||||
self.noticeBar = GuiNoticeBar(self)
|
self.noticeBar = GuiNoticeBar(self)
|
||||||
|
self.treeView = GuiDocTree(self, self.theProject)
|
||||||
self.docEditor = GuiDocEditor(self, self.theProject)
|
self.docEditor = GuiDocEditor(self, self.theProject)
|
||||||
self.docViewer = GuiDocViewer(self, self.theProject)
|
self.docViewer = GuiDocViewer(self, self.theProject)
|
||||||
self.viewMeta = GuiDocViewDetails(self, self.theProject)
|
self.viewMeta = GuiDocViewDetails(self, self.theProject)
|
||||||
self.searchBar = GuiSearchBar(self)
|
self.searchBar = GuiSearchBar(self)
|
||||||
self.treeMeta = GuiDocDetails(self, self.theProject)
|
self.treeMeta = GuiDocDetails(self, self.theProject)
|
||||||
self.treeView = GuiDocTree(self, self.theProject)
|
|
||||||
self.projView = GuiProjectOutline(self, self.theProject)
|
self.projView = GuiProjectOutline(self, self.theProject)
|
||||||
self.mainMenu = GuiMainMenu(self, self.theProject)
|
self.mainMenu = GuiMainMenu(self, self.theProject)
|
||||||
|
|
||||||
@@ -109,6 +114,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.editPane = QFrame()
|
self.editPane = QFrame()
|
||||||
self.docEdit = QVBoxLayout()
|
self.docEdit = QVBoxLayout()
|
||||||
self.docEdit.setContentsMargins(0,0,0,0)
|
self.docEdit.setContentsMargins(0,0,0,0)
|
||||||
|
self.docEdit.setSpacing(2)
|
||||||
self.docEdit.addWidget(self.searchBar)
|
self.docEdit.addWidget(self.searchBar)
|
||||||
self.docEdit.addWidget(self.noticeBar)
|
self.docEdit.addWidget(self.noticeBar)
|
||||||
self.docEdit.addWidget(self.docEditor)
|
self.docEdit.addWidget(self.docEditor)
|
||||||
@@ -117,6 +123,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.viewPane = QFrame()
|
self.viewPane = QFrame()
|
||||||
self.docView = QVBoxLayout()
|
self.docView = QVBoxLayout()
|
||||||
self.docView.setContentsMargins(0,0,0,0)
|
self.docView.setContentsMargins(0,0,0,0)
|
||||||
|
self.docView.setSpacing(2)
|
||||||
self.docView.addWidget(self.docViewer)
|
self.docView.addWidget(self.docViewer)
|
||||||
self.docView.addWidget(self.viewMeta)
|
self.docView.addWidget(self.viewMeta)
|
||||||
self.docView.setStretch(0, 1)
|
self.docView.setStretch(0, 1)
|
||||||
@@ -162,7 +169,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.viewPane.setVisible(False)
|
self.viewPane.setVisible(False)
|
||||||
self.searchBar.setVisible(False)
|
self.searchBar.setVisible(False)
|
||||||
|
|
||||||
# Build The Tree View
|
# Build the Tree View
|
||||||
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
|
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
|
||||||
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||||
self.rebuildTree()
|
self.rebuildTree()
|
||||||
@@ -172,6 +179,9 @@ class GuiMain(QMainWindow):
|
|||||||
self.setStatusBar(self.statusBar)
|
self.setStatusBar(self.statusBar)
|
||||||
self.statusBar.setStatus("Ready")
|
self.statusBar.setStatus("Ready")
|
||||||
|
|
||||||
|
# Finalise Initialisation
|
||||||
|
##########################
|
||||||
|
|
||||||
# Set Up Autosaving Project Timer
|
# Set Up Autosaving Project Timer
|
||||||
self.asProjTimer = QTimer()
|
self.asProjTimer = QTimer()
|
||||||
self.asProjTimer.timeout.connect(self._autoSaveProject)
|
self.asProjTimer.timeout.connect(self._autoSaveProject)
|
||||||
@@ -210,6 +220,8 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
logger.debug("GUI initialisation complete")
|
logger.debug("GUI initialisation complete")
|
||||||
|
|
||||||
|
# Check if a project path was provided at command line, and if
|
||||||
|
# not, open the project manager instead.
|
||||||
if self.mainConf.cmdOpen is not None:
|
if self.mainConf.cmdOpen is not None:
|
||||||
logger.debug("Opening project from additional command line option")
|
logger.debug("Opening project from additional command line option")
|
||||||
self.openProject(self.mainConf.cmdOpen)
|
self.openProject(self.mainConf.cmdOpen)
|
||||||
@@ -228,6 +240,8 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def initMain(self):
|
def initMain(self):
|
||||||
|
"""Initialise elements that depend on user settings.
|
||||||
|
"""
|
||||||
self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000))
|
self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000))
|
||||||
self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000))
|
self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000))
|
||||||
return True
|
return True
|
||||||
@@ -437,6 +451,8 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def backupProject(self):
|
def backupProject(self):
|
||||||
|
"""Trigger the project backup process.
|
||||||
|
"""
|
||||||
theBackup = NWBackup(self, self.theProject)
|
theBackup = NWBackup(self, self.theProject)
|
||||||
theBackup.zipIt()
|
theBackup.zipIt()
|
||||||
return True
|
return True
|
||||||
@@ -446,6 +462,8 @@ class GuiMain(QMainWindow):
|
|||||||
##
|
##
|
||||||
|
|
||||||
def closeDocument(self):
|
def closeDocument(self):
|
||||||
|
"""Close the document and clear the editor and title field.
|
||||||
|
"""
|
||||||
if self.hasProject:
|
if self.hasProject:
|
||||||
if self.docEditor.docChanged:
|
if self.docEditor.docChanged:
|
||||||
self.saveDocument()
|
self.saveDocument()
|
||||||
@@ -461,6 +479,7 @@ class GuiMain(QMainWindow):
|
|||||||
if self.docEditor.loadText(tHandle, tLine):
|
if self.docEditor.loadText(tHandle, tLine):
|
||||||
self.docEditor.setFocus()
|
self.docEditor.setFocus()
|
||||||
self.theProject.setLastEdited(tHandle)
|
self.theProject.setLastEdited(tHandle)
|
||||||
|
self.treeView.setSelectedHandle(tHandle)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -471,6 +490,8 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def viewDocument(self, tHandle=None):
|
def viewDocument(self, tHandle=None):
|
||||||
|
"""Load a document for viewing in the view panel.
|
||||||
|
"""
|
||||||
|
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
tHandle = self.treeView.getSelectedHandle()
|
tHandle = self.treeView.getSelectedHandle()
|
||||||
@@ -498,6 +519,9 @@ class GuiMain(QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def importDocument(self):
|
def importDocument(self):
|
||||||
|
"""Import the text contained in an out-of-project text file, and
|
||||||
|
insert the text into the currently open document.
|
||||||
|
"""
|
||||||
|
|
||||||
lastPath = self.mainConf.lastPath
|
lastPath = self.mainConf.lastPath
|
||||||
|
|
||||||
|
|||||||
@@ -601,6 +601,9 @@ class NWProject():
|
|||||||
##
|
##
|
||||||
|
|
||||||
def getItem(self, tHandle):
|
def getItem(self, tHandle):
|
||||||
|
"""Return a project item based on its handle. Returns None if
|
||||||
|
the handle doesn't exist in the project.
|
||||||
|
"""
|
||||||
if tHandle in self.projTree:
|
if tHandle in self.projTree:
|
||||||
return self.projTree[tHandle]
|
return self.projTree[tHandle]
|
||||||
logger.error("No tree item with handle %s" % str(tHandle))
|
logger.error("No tree item with handle %s" % str(tHandle))
|
||||||
@@ -626,6 +629,28 @@ class NWProject():
|
|||||||
return tHandle
|
return tHandle
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def getItemPath(self, tHandle):
|
||||||
|
"""Iterate upwards in the tree until we find the item with
|
||||||
|
parent None, the root item, and return the list of handles.
|
||||||
|
We do this with a for loop with a maximum depth of 200 to make
|
||||||
|
infinite loops impossible.
|
||||||
|
"""
|
||||||
|
tTree = []
|
||||||
|
tItem = self.getItem(tHandle)
|
||||||
|
if tItem is not None:
|
||||||
|
tTree.append(tHandle)
|
||||||
|
for i in range(200):
|
||||||
|
if tItem.parHandle is None:
|
||||||
|
return tTree
|
||||||
|
else:
|
||||||
|
tHandle = tItem.parHandle
|
||||||
|
tItem = self.getItem(tHandle)
|
||||||
|
if tItem is None:
|
||||||
|
return tTree
|
||||||
|
else:
|
||||||
|
tTree.append(tHandle)
|
||||||
|
return tTree
|
||||||
|
|
||||||
def getProjectItems(self):
|
def getProjectItems(self):
|
||||||
"""This function is called from the tree view when building the
|
"""This function is called from the tree view when building the
|
||||||
tree. Each item in the project is returned in the order saved in
|
tree. Each item in the project is returned in the order saved in
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Main]
|
[Main]
|
||||||
timestamp = 2020-04-14 22:47:16
|
timestamp = 2020-05-01 21:28:25
|
||||||
theme = default
|
theme = default
|
||||||
syntax = default_light
|
syntax = default_light
|
||||||
guidark = False
|
guidark = False
|
||||||
@@ -38,6 +38,7 @@ spellcheck = en
|
|||||||
showtabsnspaces = False
|
showtabsnspaces = False
|
||||||
showlineendings = False
|
showlineendings = False
|
||||||
bigdoclimit = 800
|
bigdoclimit = 800
|
||||||
|
showfullpath = True
|
||||||
|
|
||||||
[Backup]
|
[Backup]
|
||||||
backuppath =
|
backuppath =
|
||||||
|
|||||||
Reference in New Issue
Block a user