Merge pull request #272 from vkbo/gui_tweaks

Minor Improvements, Changes and Additions
This commit is contained in:
Veronica K. Berglyd Olsen
2020-05-31 16:01:18 +02:00
committed by GitHub
6 changed files with 184 additions and 30 deletions
+1
View File
@@ -45,6 +45,7 @@ class nwFiles():
INDEX_FILE = "tagsIndex.json" INDEX_FILE = "tagsIndex.json"
OPTS_FILE = "guiOptions.json" OPTS_FILE = "guiOptions.json"
RECENT_FILE = "recentProjects.json" RECENT_FILE = "recentProjects.json"
BUILD_CACHE = "prevBuild.json"
# END Class nwFiles # END Class nwFiles
+132 -9
View File
@@ -26,6 +26,7 @@
""" """
import logging import logging
import json
import nw import nw
from os import path from os import path
@@ -45,19 +46,21 @@ from PyQt5.QtWidgets import (
from nw.gui.additions import QSwitch from nw.gui.additions import QSwitch
from nw.core import ToHtml from nw.core import ToHtml
from nw.constants import ( from nw.constants import (
nwAlert, nwItemType, nwItemLayout, nwItemClass nwAlert, nwFiles, nwItemType, nwItemLayout, nwItemClass
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiBuildNovel(QDialog): class GuiBuildNovel(QDialog):
FMT_ODT = 1 FMT_ODT = 1
FMT_PDF = 2 FMT_PDF = 2
FMT_HTM = 3 FMT_HTM = 3
FMT_MD = 4 FMT_MD = 4
FMT_NWD = 5 FMT_NWD = 5
FMT_TXT = 6 FMT_TXT = 6
FMT_JSON_H = 7
FMT_JSON_M = 8
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent) QDialog.__init__(self, theParent)
@@ -333,7 +336,7 @@ class GuiBuildNovel(QDialog):
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD)) self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
self.saveMenu.addAction(self.saveMD) self.saveMenu.addAction(self.saveMD)
self.saveNWD = QAction("novelWriter Markdown (.nwd)", self) self.saveNWD = QAction("%s Markdown (.nwd)" % nw.__package__, self)
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD)) self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
self.saveMenu.addAction(self.saveNWD) self.saveMenu.addAction(self.saveNWD)
@@ -341,6 +344,14 @@ class GuiBuildNovel(QDialog):
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT)) self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
self.saveMenu.addAction(self.saveTXT) self.saveMenu.addAction(self.saveTXT)
self.saveJsonH = QAction("JSON + %s HTML (.json)" % nw.__package__, self)
self.saveJsonH.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_H))
self.saveMenu.addAction(self.saveJsonH)
self.saveJsonM = QAction("JSON + %s Markdown (.json)" % nw.__package__, self)
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
self.saveMenu.addAction(self.saveJsonM)
self.btnClose = QPushButton("Close") self.btnClose = QPushButton("Close")
self.btnClose.clicked.connect(self._doClose) self.btnClose.clicked.connect(self._doClose)
@@ -372,6 +383,20 @@ class GuiBuildNovel(QDialog):
logger.debug("GuiBuildNovel initialisation complete") logger.debug("GuiBuildNovel initialisation complete")
# Load from Cache
if self._loadCache():
textFont = self.textFont.text()
textSize = self.textSize.value()
justifyText = self.justifyText.isChecked()
self.docView.setTextFont(textFont, textSize)
self.docView.setJustify(justifyText)
self.docView.setStyleSheet(self.htmlStyle)
self.docView.setContent(self.htmlText)
else:
self.htmlText = []
self.htmlStyle = []
self.nwdText = []
return return
## ##
@@ -459,6 +484,8 @@ class GuiBuildNovel(QDialog):
self.docView.setStyleSheet(self.htmlStyle) self.docView.setStyleSheet(self.htmlStyle)
self.docView.setContent(self.htmlText) self.docView.setContent(self.htmlText)
self._saveCache()
return return
def _checkInclude(self, theItem, noteFiles, novelFiles, ignoreFlag): def _checkInclude(self, theItem, noteFiles, novelFiles, ignoreFlag):
@@ -534,7 +561,7 @@ class GuiBuildNovel(QDialog):
elif theFormat == self.FMT_NWD: elif theFormat == self.FMT_NWD:
fileExt = "nwd" fileExt = "nwd"
textFmt = "%s markdown" % nw.__package__ textFmt = "%s Markdown" % nw.__package__
outTool = "NW" outTool = "NW"
elif theFormat == self.FMT_TXT: elif theFormat == self.FMT_TXT:
@@ -543,6 +570,16 @@ class GuiBuildNovel(QDialog):
textFmt = "Plain Text" textFmt = "Plain Text"
outTool = "Qt" outTool = "Qt"
elif theFormat == self.FMT_JSON_H:
fileExt = "json"
textFmt = "JSON + %s HTML" % nw.__package__
outTool = "NW"
elif theFormat == self.FMT_JSON_M:
fileExt = "json"
textFmt = "JSON + %s Markdown" % nw.__package__
outTool = "NW"
else: else:
return False return False
@@ -616,6 +653,33 @@ class GuiBuildNovel(QDialog):
for aLine in self.nwdText: for aLine in self.nwdText:
outFile.write(aLine) outFile.write(aLine)
elif theFormat == self.FMT_JSON_H or theFormat == self.FMT_JSON_M:
jsonData = {
"meta" : {
"workingTitle" : self.theProject.projName,
"novelTitle" : self.theProject.bookTitle,
"authors" : self.theProject.bookAuthors,
}
}
if theFormat == self.FMT_JSON_H:
theBody = []
for htmlPage in self.htmlText:
theBody.append(htmlPage.rstrip("\n").split("\n"))
jsonData["text"] = {
"css" : self.htmlStyle,
"html" : theBody,
}
elif theFormat == self.FMT_JSON_M:
theBody = []
for nwdPage in self.nwdText:
theBody.append(nwdPage.split("\n"))
jsonData["text"] = {
"nwd" : theBody,
}
outFile.write(json.dumps(jsonData, indent=2))
wSuccess = True wSuccess = True
except Exception as e: except Exception as e:
@@ -683,6 +747,60 @@ class GuiBuildNovel(QDialog):
self.textSize.setValue(theFont.pointSize()) self.textSize.setValue(theFont.pointSize())
return return
def _loadCache(self):
"""Save the current data to cache.
"""
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
dataCount = 0
if path.isfile(buildCache):
logger.debug("Loading build cache")
try:
with open(buildCache, mode="r", encoding="utf8") as inFile:
theJson = inFile.read()
theData = json.loads(theJson)
except Exception as e:
logger.error("Failed to load build cache")
logger.error(str(e))
return False
if "htmlText" in theData.keys():
self.htmlText = theData["htmlText"]
dataCount += 1
if "htmlStyle" in theData.keys():
self.htmlStyle = theData["htmlStyle"]
dataCount += 1
if "nwdText" in theData.keys():
self.nwdText = theData["nwdText"]
dataCount += 1
return dataCount == 3
def _saveCache(self):
"""Save the current data to cache.
"""
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
if self.mainConf.debugInfo:
nIndent = 2
else:
nIndent = None
logger.debug("Saving build cache")
try:
with open(buildCache, mode="w+", encoding="utf8") as outFile:
outFile.write(json.dumps({
"htmlText" : self.htmlText,
"htmlStyle" : self.htmlStyle,
"nwdText" : self.nwdText,
}, indent=nIndent))
except Exception as e:
logger.error("Failed to save build cache")
logger.error(str(e))
return False
return True
def _doClose(self): def _doClose(self):
"""Close button was clicked. """Close button was clicked.
""" """
@@ -762,6 +880,11 @@ class GuiBuildNovelDocView(QTextBrowser):
self.qDocument = self.document() self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.textMargin) self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.setPlaceholderText(
"This area will show the content of the document to be "
"exported or printed. Press the \"Build Novel Project\" "
"button to generate content."
)
theFont = QFont() theFont = QFont()
if self.mainConf.textFont is None: if self.mainConf.textFont is None:
+12
View File
@@ -48,6 +48,7 @@ class GuiDocDetails(QFrame):
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theHandle = None
self.mainBox = QGridLayout(self) self.mainBox = QGridLayout(self)
self.mainBox.setVerticalSpacing(1) self.mainBox.setVerticalSpacing(1)
@@ -189,9 +190,20 @@ class GuiDocDetails(QFrame):
# Class Methods # Class Methods
## ##
def updateCounts(self, tHandle, cC, wC, pC):
"""Just update the counts if the handle is the same as the one
we're already showing.
"""
if tHandle == self.theHandle:
self.cCountData.setText("{:n}".format(cC))
self.wCountData.setText("{:n}".format(wC))
self.pCountData.setText("{:n}".format(pC))
return
def updateViewBox(self, tHandle): def updateViewBox(self, tHandle):
"""Populate the details box from a given handle. """Populate the details box from a given handle.
""" """
self.theHandle = tHandle
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.projTree[tHandle]
if nwItem is None: if nwItem is None:
+19 -9
View File
@@ -300,15 +300,16 @@ class GuiDocEditor(QTextEdit):
docText = self.getText() docText = self.getText()
cursPos = self.getCursorPosition() cursPos = self.getCursorPosition()
theItem = self.nwDocument.theItem self.nwDocument.theItem.setCharCount(self.charCount)
theItem.setCharCount(self.charCount) self.nwDocument.theItem.setWordCount(self.wordCount)
theItem.setWordCount(self.wordCount) self.nwDocument.theItem.setParaCount(self.paraCount)
theItem.setParaCount(self.paraCount) self.nwDocument.theItem.setCursorPos(cursPos)
theItem.setCursorPos(cursPos)
self.nwDocument.saveDocument(docText) self.nwDocument.saveDocument(docText)
self.setDocumentChanged(False) self.setDocumentChanged(False)
self.theParent.theIndex.scanText(theItem.itemHandle, docText) self.theParent.theIndex.scanText(
self.nwDocument.theItem.itemHandle, docText
)
return True return True
@@ -737,15 +738,24 @@ class GuiDocEditor(QTextEdit):
def _updateCounts(self): def _updateCounts(self):
"""Slot for the word counter's finished signal """Slot for the word counter's finished signal
""" """
if self.theHandle is None or self.nwDocument.theItem is None:
return
logger.verbose("Updating word count") logger.verbose("Updating word count")
tHandle = self.nwDocument.docHandle
self.charCount = self.wCounter.charCount self.charCount = self.wCounter.charCount
self.wordCount = self.wCounter.wordCount self.wordCount = self.wCounter.wordCount
self.paraCount = self.wCounter.paraCount self.paraCount = self.wCounter.paraCount
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount) self.nwDocument.theItem.setCharCount(self.charCount)
self.theParent.treeView.propagateCount(tHandle, self.wordCount) self.nwDocument.theItem.setWordCount(self.wordCount)
self.nwDocument.theItem.setParaCount(self.paraCount)
self.theParent.statusBar.setCounts(self.charCount, self.wordCount, self.paraCount)
self.theParent.treeView.propagateCount(self.theHandle, self.wordCount)
self.theParent.treeView.projectWordCount() self.theParent.treeView.projectWordCount()
self.theParent.treeMeta.updateCounts(
self.theHandle, self.charCount, self.wordCount, self.paraCount
)
self._checkDocSize(self.charCount) self._checkDocSize(self.charCount)
return return
+1 -1
View File
@@ -201,7 +201,7 @@ class GuiMainStatus(QStatusBar):
"""Update statistics. """Update statistics.
""" """
self.statsText.setToolTip( self.statsText.setToolTip(
"D: Document word count<br>P: Project word count" "D: Document word count<br>P: Project word count (session change)"
) )
self.statsText.setText(( self.statsText.setText((
"D:{wC:n} P:{pWC:n} ({sWC:+n})" "D:{wC:n} P:{pWC:n} ({sWC:+n})"
+19 -11
View File
@@ -1019,25 +1019,33 @@ class GuiMain(QMainWindow):
return return
def _treeDoubleClick(self, tItem, colNo): def _treeDoubleClick(self, tItem, colNo):
tHandle = tItem.text(3) """The user double-clicked an item in the tree. If it is a file,
we open it. Otherwise, we do nothing.
"""
tHandle = tItem.text(self.treeView.C_HANDLE)
logger.verbose("User double clicked tree item with handle %s" % tHandle) logger.verbose("User double clicked tree item with handle %s" % tHandle)
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE: if nwItem is not None:
logger.verbose("Requested item %s is a file" % tHandle) if nwItem.itemType == nwItemType.FILE:
self.openDocument(tHandle) logger.verbose("Requested item %s is a file" % tHandle)
else: self.openDocument(tHandle)
logger.verbose("Requested item %s is a folder" % tHandle) else:
logger.verbose("Requested item %s is a folder" % tHandle)
return return
def _treeKeyPressReturn(self): def _treeKeyPressReturn(self):
"""The user pressed return an item in the tree. If it is a file,
we open it. Otherwise, we do nothing.
"""
tHandle = self.treeView.getSelectedHandle() tHandle = self.treeView.getSelectedHandle()
logger.verbose("User pressed return on tree item with handle %s" % tHandle) logger.verbose("User pressed return on tree item with handle %s" % tHandle)
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE: if nwItem is not None:
logger.verbose("Requested item %s is a file" % tHandle) if nwItem.itemType == nwItemType.FILE:
self.openDocument(tHandle) logger.verbose("Requested item %s is a file" % tHandle)
else: self.openDocument(tHandle)
logger.verbose("Requested item %s is a folder" % tHandle) else:
logger.verbose("Requested item %s is a folder" % tHandle)
return return
def _keyPressEscape(self): def _keyPressEscape(self):