Merge pull request #272 from vkbo/gui_tweaks
Minor Improvements, Changes and Additions
This commit is contained in:
@@ -45,6 +45,7 @@ class nwFiles():
|
||||
INDEX_FILE = "tagsIndex.json"
|
||||
OPTS_FILE = "guiOptions.json"
|
||||
RECENT_FILE = "recentProjects.json"
|
||||
BUILD_CACHE = "prevBuild.json"
|
||||
|
||||
# END Class nwFiles
|
||||
|
||||
|
||||
+132
-9
@@ -26,6 +26,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
import json
|
||||
import nw
|
||||
|
||||
from os import path
|
||||
@@ -45,19 +46,21 @@ from PyQt5.QtWidgets import (
|
||||
from nw.gui.additions import QSwitch
|
||||
from nw.core import ToHtml
|
||||
from nw.constants import (
|
||||
nwAlert, nwItemType, nwItemLayout, nwItemClass
|
||||
nwAlert, nwFiles, nwItemType, nwItemLayout, nwItemClass
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class GuiBuildNovel(QDialog):
|
||||
|
||||
FMT_ODT = 1
|
||||
FMT_PDF = 2
|
||||
FMT_HTM = 3
|
||||
FMT_MD = 4
|
||||
FMT_NWD = 5
|
||||
FMT_TXT = 6
|
||||
FMT_ODT = 1
|
||||
FMT_PDF = 2
|
||||
FMT_HTM = 3
|
||||
FMT_MD = 4
|
||||
FMT_NWD = 5
|
||||
FMT_TXT = 6
|
||||
FMT_JSON_H = 7
|
||||
FMT_JSON_M = 8
|
||||
|
||||
def __init__(self, theParent, theProject):
|
||||
QDialog.__init__(self, theParent)
|
||||
@@ -333,7 +336,7 @@ class GuiBuildNovel(QDialog):
|
||||
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
|
||||
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.saveMenu.addAction(self.saveNWD)
|
||||
|
||||
@@ -341,6 +344,14 @@ class GuiBuildNovel(QDialog):
|
||||
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
||||
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.clicked.connect(self._doClose)
|
||||
|
||||
@@ -372,6 +383,20 @@ class GuiBuildNovel(QDialog):
|
||||
|
||||
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
|
||||
|
||||
##
|
||||
@@ -459,6 +484,8 @@ class GuiBuildNovel(QDialog):
|
||||
self.docView.setStyleSheet(self.htmlStyle)
|
||||
self.docView.setContent(self.htmlText)
|
||||
|
||||
self._saveCache()
|
||||
|
||||
return
|
||||
|
||||
def _checkInclude(self, theItem, noteFiles, novelFiles, ignoreFlag):
|
||||
@@ -534,7 +561,7 @@ class GuiBuildNovel(QDialog):
|
||||
|
||||
elif theFormat == self.FMT_NWD:
|
||||
fileExt = "nwd"
|
||||
textFmt = "%s markdown" % nw.__package__
|
||||
textFmt = "%s Markdown" % nw.__package__
|
||||
outTool = "NW"
|
||||
|
||||
elif theFormat == self.FMT_TXT:
|
||||
@@ -543,6 +570,16 @@ class GuiBuildNovel(QDialog):
|
||||
textFmt = "Plain Text"
|
||||
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:
|
||||
return False
|
||||
|
||||
@@ -616,6 +653,33 @@ class GuiBuildNovel(QDialog):
|
||||
for aLine in self.nwdText:
|
||||
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
|
||||
|
||||
except Exception as e:
|
||||
@@ -683,6 +747,60 @@ class GuiBuildNovel(QDialog):
|
||||
self.textSize.setValue(theFont.pointSize())
|
||||
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):
|
||||
"""Close button was clicked.
|
||||
"""
|
||||
@@ -762,6 +880,11 @@ class GuiBuildNovelDocView(QTextBrowser):
|
||||
|
||||
self.qDocument = self.document()
|
||||
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()
|
||||
if self.mainConf.textFont is None:
|
||||
|
||||
@@ -48,6 +48,7 @@ class GuiDocDetails(QFrame):
|
||||
self.theParent = theParent
|
||||
self.theProject = theProject
|
||||
self.theTheme = theParent.theTheme
|
||||
self.theHandle = None
|
||||
|
||||
self.mainBox = QGridLayout(self)
|
||||
self.mainBox.setVerticalSpacing(1)
|
||||
@@ -189,9 +190,20 @@ class GuiDocDetails(QFrame):
|
||||
# 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):
|
||||
"""Populate the details box from a given handle.
|
||||
"""
|
||||
self.theHandle = tHandle
|
||||
nwItem = self.theProject.projTree[tHandle]
|
||||
|
||||
if nwItem is None:
|
||||
|
||||
@@ -300,15 +300,16 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
docText = self.getText()
|
||||
cursPos = self.getCursorPosition()
|
||||
theItem = self.nwDocument.theItem
|
||||
theItem.setCharCount(self.charCount)
|
||||
theItem.setWordCount(self.wordCount)
|
||||
theItem.setParaCount(self.paraCount)
|
||||
theItem.setCursorPos(cursPos)
|
||||
self.nwDocument.theItem.setCharCount(self.charCount)
|
||||
self.nwDocument.theItem.setWordCount(self.wordCount)
|
||||
self.nwDocument.theItem.setParaCount(self.paraCount)
|
||||
self.nwDocument.theItem.setCursorPos(cursPos)
|
||||
self.nwDocument.saveDocument(docText)
|
||||
self.setDocumentChanged(False)
|
||||
|
||||
self.theParent.theIndex.scanText(theItem.itemHandle, docText)
|
||||
self.theParent.theIndex.scanText(
|
||||
self.nwDocument.theItem.itemHandle, docText
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@@ -737,15 +738,24 @@ class GuiDocEditor(QTextEdit):
|
||||
def _updateCounts(self):
|
||||
"""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")
|
||||
|
||||
tHandle = self.nwDocument.docHandle
|
||||
self.charCount = self.wCounter.charCount
|
||||
self.wordCount = self.wCounter.wordCount
|
||||
self.paraCount = self.wCounter.paraCount
|
||||
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
|
||||
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
|
||||
self.nwDocument.theItem.setCharCount(self.charCount)
|
||||
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.treeMeta.updateCounts(
|
||||
self.theHandle, self.charCount, self.wordCount, self.paraCount
|
||||
)
|
||||
self._checkDocSize(self.charCount)
|
||||
|
||||
return
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ class GuiMainStatus(QStatusBar):
|
||||
"""Update statistics.
|
||||
"""
|
||||
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((
|
||||
"D:{wC:n} P:{pWC:n} ({sWC:+n})"
|
||||
|
||||
+19
-11
@@ -1019,25 +1019,33 @@ class GuiMain(QMainWindow):
|
||||
return
|
||||
|
||||
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)
|
||||
nwItem = self.theProject.projTree[tHandle]
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
logger.verbose("Requested item %s is a file" % tHandle)
|
||||
self.openDocument(tHandle)
|
||||
else:
|
||||
logger.verbose("Requested item %s is a folder" % tHandle)
|
||||
if nwItem is not None:
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
logger.verbose("Requested item %s is a file" % tHandle)
|
||||
self.openDocument(tHandle)
|
||||
else:
|
||||
logger.verbose("Requested item %s is a folder" % tHandle)
|
||||
return
|
||||
|
||||
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()
|
||||
logger.verbose("User pressed return on tree item with handle %s" % tHandle)
|
||||
nwItem = self.theProject.projTree[tHandle]
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
logger.verbose("Requested item %s is a file" % tHandle)
|
||||
self.openDocument(tHandle)
|
||||
else:
|
||||
logger.verbose("Requested item %s is a folder" % tHandle)
|
||||
if nwItem is not None:
|
||||
if nwItem.itemType == nwItemType.FILE:
|
||||
logger.verbose("Requested item %s is a file" % tHandle)
|
||||
self.openDocument(tHandle)
|
||||
else:
|
||||
logger.verbose("Requested item %s is a folder" % tHandle)
|
||||
return
|
||||
|
||||
def _keyPressEscape(self):
|
||||
|
||||
Reference in New Issue
Block a user