Done building the buttons etc for BuildNovel dialog

This commit is contained in:
Veronica K. B. Olsen
2020-05-10 19:31:53 +02:00
parent 5ab1402854
commit 4d9e2d03a3
6 changed files with 400 additions and 23 deletions
+44
View File
@@ -0,0 +1,44 @@
<h1>Help!</h1>
<p>A brief guide to make the most out of the Build Project tool.</p>
<h2>Novel Title Formats</h2>
<p>The format of the various title levels in the files under the Novel folder can be customised in
these settings. The actual title given in the headings of your files will replace all
occurrences of the keyword <mark>%title%</mark>. Any static text will be left as-is in the
final title. An empty field means the title isn't written out at all.</p>
<p>The available formatting keywords are:</p>
<p><mark>%title%</mark> &ndash; This is replaced with the text you put in your headings in your
documents</p>
<p><mark>%num%</mark> &ndash; This is replaced with the chapter number of your chapter type
headings. These are generated automaticall starting from 1.</p>
<p><mark>%numword%</mark> &ndash; This is replaced with the chapter number of your chapter type
headings, but instead of an arabic number, the word for it is used instead, e.g. One, Two,
Fifteen, Twenty-Five, etc.</p>
<p><mark>\\</mark> &ndash; Two backslashes are replaced by a line break.</p>
<p><b>Note:</b> The Scene format is treated slightly differently than the other title formats. If a
scene format is a constant text, that is, contains no <mark>%title%</mark>, it will be treated
as a scene separator instead. Scene separators are centred, and not shown if the chapter starts
directly on the first scene. If the field is blank, a large space between the scenes is added
instead.</p>
<h2>Build Overrides</h2>
<p><b>Novel Outline Mode:</b> This option will build an outline version of the novel rather than the
full thing. It overrides the title format settings without changing them. Each title will be
written out, and the synopsis text will appear instead of the body text of the files. Some of
the other options are still available in Outline Mode.</p>
<h2>Include Non-Text Elements</h2>
<p><b>Include Synopsis:</b> This will add the synopsis comment as the first paragraph after each
heading.</p>
<p><b>Include Comments:</b> This will include any comments as additional paragraphs in the text.</p>
<p><b>Include Keywords:</b> This will include any keywords and tags as clickable links after each
heading.</p>
<h2>Additional Options</h2>
<p><b>Include Novel Files:</b> This means all files that don't have a layout of type "Note" will be
included. This is the normal mode when exporting the novel itself without the notes.</p>
<p><b>Include Note Files:</b> This means all files with a layout of type "Note" <i>will</i> be
included. Titles in note files are always left as they appear.</p>
<p><b>Ignore Export Flag:</b> Each file in the project tree has an "Include when building project"
option set, which is indicated by a little check mark in the "Flags" column. Files without This
tick will normally be skipped during build, but can be included if this option is enabled.</p>
+1
View File
@@ -84,6 +84,7 @@ class Config:
self.guiTheme = "default"
self.guiSyntax = "default_light"
self.guiDark = False
self.guiLang = "en" # Hardcoded for now
## Sizes
self.winGeometry = [1100, 650]
+13 -10
View File
@@ -200,13 +200,14 @@ class NWProject():
self.bookAuthors = []
self.autoReplace = {}
self.titleFormat = {
"title": "%title%",
"chapter": "Chapter %num%",
"chapterSub": "%title%",
"unnumbered": "%title%",
"scene": "",
"sceneSep": "* * *",
"section": "",
"title" : r"%title%",
"chapter" : r"Chapter %num%\\%title%",
"unnumbered" : r"%title%",
"scene" : r"* * *",
"section" : r"",
"withSynopsis" : False,
"withComments" : False,
"withKeywords" : False,
}
self.spellCheck = False
self.autoOutline = True
@@ -717,9 +718,11 @@ class NWProject():
def setTitleFormat(self, titleFormat):
"""Set the formatting of titles in the project.
"""
for valKey in titleFormat:
if valKey in self.titleFormat:
self.titleFormat[valKey] = titleFormat[valKey]
for valKey, valEntry in titleFormat.items():
if valKey in ("title","chapter","unnumbered","scene","section"):
self.titleFormat[valKey] = checkString(valEntry, self.titleFormat[valKey], False)
elif valKey in ("withSynopsis","withComments","withKeywords"):
self.titleFormat[valKey] = checkBool(valEntry, False, False)
return
def setProjectChanged(self, bValue):
+5
View File
@@ -165,6 +165,11 @@ class Tokenizer():
return
def getResult(self):
"""Return the result from the conversion.
"""
return self.theResult
def doAutoReplace(self):
"""Run through the user's auto-replace dictionary.
"""
+330 -7
View File
@@ -28,18 +28,29 @@
import logging
import nw
from os import path
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextOption, QPalette, QColor
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QTextBrowser
QDialog, QVBoxLayout, QHBoxLayout, QTextBrowser, QPushButton,
QLabel, QLineEdit, QGroupBox, QGridLayout, QComboBox, QProgressBar,
QMenu, QAction
)
from nw.constants import nwConst, nwFiles, nwAlert
from nw.gui.additions import QSwitch
from nw.core import ToHtml
from nw.constants import nwConst, nwFiles, nwAlert, nwItemType
logger = logging.getLogger(__name__)
class GuiBuildNovel(QDialog):
FMT_ODT = 1
FMT_PDF = 2
FMT_HTM = 3
FMT_MD = 4
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
@@ -48,28 +59,310 @@ class GuiBuildNovel(QDialog):
self.mainConf = nw.CONFIG
self.theProject = theProject
self.theParent = theParent
self.theTheme = theParent.theTheme
self.optState = self.theProject.optState
self.setWindowTitle("Build Project")
self.setMinimumWidth(400)
self.setMinimumHeight(400)
self.setMinimumWidth(800)
self.setMinimumHeight(700)
self.resize(
self.optState.getInt("GuiBuildNovel", "winWidth", 800),
self.optState.getInt("GuiBuildNovel", "winHeight", 700)
)
self.outerBox = QVBoxLayout()
self.innerBox = QHBoxLayout()
self.toolsBox = QVBoxLayout()
self.docView = GuiBuildNovelDocView(self, self.theProject)
# Title Formats
# =============
self.titleGroup = QGroupBox("Novel Title Formats", self)
self.titleForm = QGridLayout(self)
self.titleGroup.setLayout(self.titleForm)
self.fmtTitle = QLineEdit()
self.fmtTitle.setMaxLength(200)
self.fmtTitle.setFixedWidth(200)
self.fmtTitle.setText(self.theProject.titleFormat["title"])
self.fmtChapter = QLineEdit()
self.fmtChapter.setMaxLength(200)
self.fmtChapter.setFixedWidth(200)
self.fmtChapter.setText(self.theProject.titleFormat["chapter"])
self.fmtUnnumbered = QLineEdit()
self.fmtUnnumbered.setMaxLength(200)
self.fmtUnnumbered.setFixedWidth(200)
self.fmtUnnumbered.setText(self.theProject.titleFormat["unnumbered"])
self.fmtScene = QLineEdit()
self.fmtScene.setMaxLength(200)
self.fmtScene.setFixedWidth(200)
self.fmtScene.setText(self.theProject.titleFormat["scene"])
self.fmtSection = QLineEdit()
self.fmtSection.setMaxLength(200)
self.fmtSection.setFixedWidth(200)
self.fmtSection.setText(self.theProject.titleFormat["section"])
self.titleForm.addWidget(QLabel("Title"), 0, 0)
self.titleForm.addWidget(self.fmtTitle, 0, 1)
self.titleForm.addWidget(QLabel("Chapter"), 1, 0)
self.titleForm.addWidget(self.fmtChapter, 1, 1)
self.titleForm.addWidget(QLabel("Unnumbered"), 2, 0)
self.titleForm.addWidget(self.fmtUnnumbered, 2, 1)
self.titleForm.addWidget(QLabel("Scene"), 3, 0)
self.titleForm.addWidget(self.fmtScene, 3, 1)
self.titleForm.addWidget(QLabel("Section"), 4, 0)
self.titleForm.addWidget(self.fmtSection, 4, 1)
self.titleForm.setColumnStretch(0, 1)
self.titleForm.setColumnStretch(1, 0)
# Build Settings
# ==============
self.buildGroup = QGroupBox("Build Overrides", self)
self.buildForm = QGridLayout(self)
self.buildGroup.setLayout(self.buildForm)
self.outlineMode = QSwitch()
self.outlineMode.setChecked(self.optState.getBool("GuiBuildNovel", "outlineMode", False))
self.buildForm.addWidget(QLabel("Novel Outline Mode"), 0, 0)
self.buildForm.addWidget(self.outlineMode, 0, 1)
self.buildForm.setColumnStretch(0, 1)
self.buildForm.setColumnStretch(1, 0)
# Include Switches
# ================
self.includeGroup = QGroupBox("Include Non-Text Elements", self)
self.includeForm = QGridLayout(self)
self.includeGroup.setLayout(self.includeForm)
self.includeSynopsis = QSwitch()
self.includeSynopsis.setChecked(self.theProject.titleFormat["withSynopsis"])
self.includeComments = QSwitch()
self.includeComments.setChecked(self.theProject.titleFormat["withComments"])
self.includeKeywords = QSwitch()
self.includeKeywords.setChecked(self.theProject.titleFormat["withKeywords"])
self.includeForm.addWidget(QLabel("Include Synopsis"), 0, 0)
self.includeForm.addWidget(self.includeSynopsis, 0, 1)
self.includeForm.addWidget(QLabel("Include Comments"), 1, 0)
self.includeForm.addWidget(self.includeComments, 1, 1)
self.includeForm.addWidget(QLabel("Include Keywords"), 2, 0)
self.includeForm.addWidget(self.includeKeywords, 2, 1)
self.includeForm.setColumnStretch(0, 1)
self.includeForm.setColumnStretch(1, 0)
# Additional Options
# ==================
self.addsGroup = QGroupBox("Additional Options", self)
self.addsForm = QGridLayout(self)
self.addsGroup.setLayout(self.addsForm)
self.novelFiles = QSwitch()
self.novelFiles.setChecked(self.optState.getBool("GuiBuildNovel", "addNovel", True))
self.noteFiles = QSwitch()
self.noteFiles.setChecked(self.optState.getBool("GuiBuildNovel", "addNotes", False))
self.ignoreFlag = QSwitch()
self.ignoreFlag.setChecked(self.optState.getBool("GuiBuildNovel", "ignoreFlag", False))
self.addsForm.addWidget(QLabel("Include Novel Files"), 0, 0)
self.addsForm.addWidget(self.novelFiles, 0, 1)
self.addsForm.addWidget(QLabel("Include Note Files"), 1, 0)
self.addsForm.addWidget(self.noteFiles, 1, 1)
self.addsForm.addWidget(QLabel("Ignore Export Flag"), 2, 0)
self.addsForm.addWidget(self.ignoreFlag, 2, 1)
self.addsForm.setColumnStretch(0, 1)
self.addsForm.setColumnStretch(1, 0)
# Build Button
# ============
self.buildProgress = QProgressBar()
self.genPreview = QPushButton("Generate Preview")
self.genPreview.clicked.connect(self._buildPreview)
# Action Buttons
# ==============
self.buttonForm = QGridLayout()
self.btnHelp = QPushButton("Help")
self.btnHelp.clicked.connect(self._showHelp)
self.btnPrint = QPushButton("Print")
self.btnPrint.clicked.connect(self._printDocument)
self.btnSave = QPushButton("Save As")
self.saveMenu = QMenu(self)
self.saveODT = QAction("Open Document (.odt)")
self.savePDF = QAction("Portable Document (.pdf)")
self.saveHTM = QAction("HTML5 (.htm)")
self.saveMD = QAction("Markdown (.md)")
self.saveODT.triggered.connect(lambda: self._saveDocument(self.FMT_ODT))
self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
self.saveHTM.triggered.connect(lambda: self._saveDocument(self.FMT_HTM))
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
self.saveMenu.addAction(self.saveODT)
self.saveMenu.addAction(self.savePDF)
self.saveMenu.addAction(self.saveHTM)
self.saveMenu.addAction(self.saveMD)
self.btnSave.setMenu(self.saveMenu)
self.btnClose = QPushButton("Close")
self.btnClose.clicked.connect(self._doClose)
self.buttonForm.addWidget(self.btnHelp, 0, 0)
self.buttonForm.addWidget(self.btnPrint, 0, 1)
self.buttonForm.addWidget(self.btnSave, 1, 0)
self.buttonForm.addWidget(self.btnClose, 1, 1)
# Assemble GUI
# ============
self.toolsBox.addWidget(self.titleGroup)
self.toolsBox.addWidget(self.buildGroup)
self.toolsBox.addWidget(self.includeGroup)
self.toolsBox.addWidget(self.addsGroup)
self.toolsBox.addStretch(1)
self.toolsBox.addWidget(self.buildProgress)
self.toolsBox.addWidget(self.genPreview)
self.toolsBox.addSpacing(8)
self.toolsBox.addLayout(self.buttonForm)
self.innerBox.addLayout(self.toolsBox)
self.innerBox.addWidget(self.docView)
self.outerBox.addLayout(self.innerBox)
self.setLayout(self.outerBox)
self.innerBox.setStretch(0, 0)
self.innerBox.setStretch(1, 1)
self.outlineMode.toggled.connect(self._toggelOutlineMode)
self._toggelOutlineMode(self.outlineMode.isChecked())
self.show()
logger.debug("GuiBuildNovel initialisation complete")
return
##
# Slots
##
def _buildPreview(self):
"""Build a preview of the project in the document viewer.
"""
makeHtml = ToHtml(self.theProject, self.theParent)
theText = ""
for tItem in self.theProject.projTree:
if tItem is not None and tItem.itemType == nwItemType.FILE:
makeHtml.setText(tItem.itemHandle)
makeHtml.doAutoReplace()
makeHtml.tokenizeText()
makeHtml.doHeaders()
makeHtml.doConvert()
makeHtml.doPostProcessing()
theText += makeHtml.getResult()
self.docView.setHtml(theText)
return
def _saveDocument(self, theFormat):
return
def _printDocument(self):
return
def _toggelOutlineMode(self, theState):
"""Enables or disables the options that are overridden in#
outline mode.
"""
self.fmtTitle.setEnabled(not theState)
self.fmtChapter.setEnabled(not theState)
self.fmtUnnumbered.setEnabled(not theState)
self.fmtScene.setEnabled(not theState)
self.fmtSection.setEnabled(not theState)
self.includeSynopsis.setEnabled(not theState)
self.novelFiles.setEnabled(not theState)
self.noteFiles.setEnabled(not theState)
return
def _doClose(self):
"""Close button was clicked.
"""
self.close()
return
##
# Events
##
def closeEvent(self, theEvent):
"""Capture the user closing the window so we can save settings.
"""
self._saveSettings()
QDialog.closeEvent(self, theEvent)
return
##
# Internal Functions
##
def _saveSettings(self):
"""Save the various user settings.
"""
logger.debug("Saving GuiBuildNovel settings")
# Formatting
self.theProject.setTitleFormat({
"title" : self.fmtTitle.text().strip(),
"chapter" : self.fmtChapter.text().strip(),
"unnumbered" : self.fmtUnnumbered.text().strip(),
"scene" : self.fmtScene.text().strip(),
"section" : self.fmtSection.text().strip(),
"withSynopsis" : self.includeSynopsis.isChecked(),
"withComments" : self.includeComments.isChecked(),
"withKeywords" : self.includeKeywords.isChecked(),
})
# GUI Settings
self.optState.setValue("GuiBuildNovel", "winWidth", self.width())
self.optState.setValue("GuiBuildNovel", "winHeight", self.height())
self.optState.setValue("GuiBuildNovel", "outlineMode", self.outlineMode.isChecked())
self.optState.setValue("GuiBuildNovel", "addNovel", self.novelFiles.isChecked())
self.optState.setValue("GuiBuildNovel", "addNotes", self.noteFiles.isChecked())
self.optState.setValue("GuiBuildNovel", "ignoreFlag", self.ignoreFlag.isChecked())
self.optState.saveSettings()
return
def _showHelp(self):
"""Generate a help text and show it in the document window.
"""
docName = "exportHelp_%s.htm" % self.mainConf.guiLang
docPath = path.join(self.mainConf.assetPath, "text", docName)
if path.isfile(docPath):
with open(docPath, mode="r", encoding="utf8") as inFile:
helpText = inFile.read()
self.docView.setText(helpText)
else:
self.theParent.makeAlert(
"Could not open help text file for Build Project.", nwAlert.ERROR
)
return
# END Class GuiBuildNovel
class GuiBuildNovelDocView(QTextBrowser):
@@ -83,10 +376,12 @@ class GuiBuildNovelDocView(QTextBrowser):
self.theProject = theProject
self.theParent = theParent
self.qDocument = self.document()
self.setMinimumWidth(300)
self.setMinimumWidth(400)
self.setOpenExternalLinks(False)
self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
theOpt = QTextOption()
if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify)
@@ -97,7 +392,7 @@ class GuiBuildNovelDocView(QTextBrowser):
docPalette.setColor(QPalette.Text, QColor( 0, 0, 0))
self.setPalette(docPalette)
self.setHtml("<h1>Hello World</h1><p>Some text ...</p>")
self._makeStyleSheet()
self.show()
@@ -105,4 +400,32 @@ class GuiBuildNovelDocView(QTextBrowser):
return
def setText(self, theText):
self.setHtml(theText)
return
##
# Internal Functions
##
def _makeStyleSheet(self):
styleSheet = (
"h1, h2 {"
" color: rgb(66, 113, 174);"
"}\n"
"h3, h4 {"
" color: rgb(50, 50, 50);"
"}\n"
"a {"
" color: rgb(137, 89, 168);"
"}\n"
"mark {"
" background-color: rgb(240, 198, 116);"
"}\n"
)
self.qDocument.setDefaultStyleSheet(styleSheet)
return
# END Class GuiBuildNovelDocView
+7 -6
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="171" autoCount="20" timeStamp="2020-05-10 15:56:41">
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="229" autoCount="28" timeStamp="2020-05-10 19:30:40">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
@@ -20,12 +20,13 @@
</autoReplace>
<titleFormat>
<title>%title%</title>
<chapter>Chapter %num%</chapter>
<chapterSub>%title%</chapterSub>
<chapter>Chapter %num%\\%title%</chapter>
<unnumbered>%title%</unnumbered>
<scene>None</scene>
<sceneSep>* * *</sceneSep>
<section>None</section>
<scene>* * *</scene>
<section></section>
<withSynopsis>True</withSynopsis>
<withComments>False</withComments>
<withKeywords>False</withKeywords>
</titleFormat>
<status>
<entry blue="100" green="100" red="100">New</entry>