Finished cleaning up formatting on export and connected all dialog options
This commit is contained in:
+42
-17
@@ -104,15 +104,24 @@ class ToHtml(Tokenizer):
|
|||||||
thisPar = []
|
thisPar = []
|
||||||
for tType, tText, tFormat, tAlign in self.theTokens:
|
for tType, tText, tFormat, tAlign in self.theTokens:
|
||||||
|
|
||||||
|
# Styles
|
||||||
aStyle = []
|
aStyle = []
|
||||||
if tAlign == self.A_CENTRE:
|
if tAlign == self.A_CENTRE:
|
||||||
aStyle.append("text-align: center;")
|
aStyle.append("text-align: center;")
|
||||||
|
elif tAlign == self.A_RIGHT:
|
||||||
|
aStyle.append("text-align: right;")
|
||||||
|
elif tAlign == self.A_JUSTIFY:
|
||||||
|
aStyle.append("text-align: justify;")
|
||||||
|
|
||||||
|
if tType == self.T_HEAD2:
|
||||||
|
aStyle.append("page-break-before: always;")
|
||||||
|
|
||||||
if len(aStyle) > 0:
|
if len(aStyle) > 0:
|
||||||
hStyle = " style='%s'" % (" ".join(aStyle))
|
hStyle = " style='%s'" % (" ".join(aStyle))
|
||||||
else:
|
else:
|
||||||
hStyle = ""
|
hStyle = ""
|
||||||
|
|
||||||
|
# Process TextType
|
||||||
if tType == self.T_EMPTY:
|
if tType == self.T_EMPTY:
|
||||||
if len(thisPar) > 0:
|
if len(thisPar) > 0:
|
||||||
tTemp = "".join(thisPar)
|
tTemp = "".join(thisPar)
|
||||||
@@ -120,23 +129,30 @@ class ToHtml(Tokenizer):
|
|||||||
thisPar = []
|
thisPar = []
|
||||||
|
|
||||||
elif tType == self.T_HEAD1:
|
elif tType == self.T_HEAD1:
|
||||||
self.theResult += "<h1%s>%s</h1>\n" % (hStyle,tText)
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
|
self.theResult += "<h1%s>%s</h1>\n" % (hStyle, tHead)
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2:
|
||||||
self.theResult += "<h2%s>%s</h2>\n" % (hStyle,tText)
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
|
self.theResult += "<h2%s>%s</h2>\n" % (hStyle, tHead)
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
self.theResult += "<h3%s>%s</h3>\n" % (hStyle,tText)
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
|
self.theResult += "<h3%s>%s</h3>\n" % (hStyle, tHead)
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
self.theResult += "<h4%s>%s</h4>\n" % (hStyle,tText)
|
tHead = tText.replace(r"\\", "<br/>")
|
||||||
|
self.theResult += "<h4%s>%s</h4>\n" % (hStyle, tHead)
|
||||||
|
|
||||||
elif tType == self.T_SEP:
|
elif tType == self.T_SEP:
|
||||||
self.theResult += "<p%s>%s</p>\n" % (hStyle,tText)
|
self.theResult += "<p%s>%s</p>\n" % (hStyle, tText)
|
||||||
|
|
||||||
elif tType == self.T_SKIP:
|
elif tType == self.T_SKIP:
|
||||||
self.theResult += "<p> </p>\n"
|
self.theResult += "<p> </p>\n"
|
||||||
|
|
||||||
|
elif tType == self.T_PBREAK:
|
||||||
|
self.theResult += "<p style='page-break-after: always;'> </p>\n"
|
||||||
|
|
||||||
elif tType == self.T_TEXT:
|
elif tType == self.T_TEXT:
|
||||||
tTemp = tText
|
tTemp = tText
|
||||||
for xPos, xLen, xFmt in reversed(tFormat):
|
for xPos, xLen, xFmt in reversed(tFormat):
|
||||||
@@ -146,6 +162,9 @@ class ToHtml(Tokenizer):
|
|||||||
else:
|
else:
|
||||||
thisPar.append(tTemp.rstrip()+" ")
|
thisPar.append(tTemp.rstrip()+" ")
|
||||||
|
|
||||||
|
elif tType == self.T_SYNOPSIS and self.doSynopsis:
|
||||||
|
self.theResult += self._formatSynopsis(tText)
|
||||||
|
|
||||||
elif tType == self.T_COMMENT and self.doComments:
|
elif tType == self.T_COMMENT and self.doComments:
|
||||||
self.theResult += self._formatComments(tText)
|
self.theResult += self._formatComments(tText)
|
||||||
|
|
||||||
@@ -158,12 +177,27 @@ class ToHtml(Tokenizer):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _formatKeywords(self, tText):
|
def _formatSynopsis(self, tText):
|
||||||
"""Apply HTML formatting to keywords.
|
"""Apply HTML formatting to synopsis.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.forPreview:
|
if not self.forPreview:
|
||||||
return "<pre>@%s</pre>\n" % tText
|
return "<p class='synopsis'><strong>Synopsis: </strong>%s</p>\n" % tText
|
||||||
|
|
||||||
|
return "<p class='comment'>%s</p>\n" % tText
|
||||||
|
|
||||||
|
def _formatComments(self, tText):
|
||||||
|
"""Apply HTML formatting to comments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.forPreview:
|
||||||
|
return "<p class='comment'><strong>Comment: </strong>%s</p>\n" % tText
|
||||||
|
|
||||||
|
return "<p class='comment'>%s</p>\n" % tText
|
||||||
|
|
||||||
|
def _formatKeywords(self, tText):
|
||||||
|
"""Apply HTML formatting to keywords.
|
||||||
|
"""
|
||||||
|
|
||||||
tText = "@"+tText
|
tText = "@"+tText
|
||||||
isValid, theBits, thePos = self.theParent.theIndex.scanThis(tText)
|
isValid, theBits, thePos = self.theParent.theIndex.scanThis(tText)
|
||||||
@@ -182,13 +216,4 @@ class ToHtml(Tokenizer):
|
|||||||
|
|
||||||
return "<div>%s</div>" % retText
|
return "<div>%s</div>" % retText
|
||||||
|
|
||||||
def _formatComments(self, tText):
|
|
||||||
"""Apply HTML formatting to comments.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self.forPreview:
|
|
||||||
return "<div class='comment'>%s</div>\n" % tText
|
|
||||||
|
|
||||||
return "<p class='comment'>%s</p>\n" % tText
|
|
||||||
|
|
||||||
# END Class ToHtml
|
# END Class ToHtml
|
||||||
|
|||||||
+81
-52
@@ -40,29 +40,30 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Tokenizer():
|
class Tokenizer():
|
||||||
|
|
||||||
FMT_B_B = 1 # Begin bold
|
FMT_B_B = 1 # Begin bold
|
||||||
FMT_B_E = 2 # End bold
|
FMT_B_E = 2 # End bold
|
||||||
FMT_I_B = 3 # Begin italics
|
FMT_I_B = 3 # Begin italics
|
||||||
FMT_I_E = 4 # End italics
|
FMT_I_E = 4 # End italics
|
||||||
FMT_U_B = 5 # Begin underline
|
FMT_U_B = 5 # Begin underline
|
||||||
FMT_U_E = 6 # End underline
|
FMT_U_E = 6 # End underline
|
||||||
|
|
||||||
T_EMPTY = 1 # Empty line (new paragraph)
|
T_EMPTY = 1 # Empty line (new paragraph)
|
||||||
T_COMMENT = 2 # Comment line
|
T_SYNOPSIS = 2 # Synopsis comment
|
||||||
T_KEYWORD = 3 # Command line
|
T_COMMENT = 3 # Comment line
|
||||||
T_HEAD1 = 4 # Header 1 (title)
|
T_KEYWORD = 4 # Command line
|
||||||
T_HEAD2 = 5 # Header 2 (chapter)
|
T_HEAD1 = 5 # Header 1 (title)
|
||||||
T_HEAD3 = 6 # Header 3 (scene)
|
T_HEAD2 = 6 # Header 2 (chapter)
|
||||||
T_HEAD4 = 7 # Header 4
|
T_HEAD3 = 7 # Header 3 (scene)
|
||||||
T_TEXT = 8 # Text line
|
T_HEAD4 = 8 # Header 4
|
||||||
T_SEP = 9 # Scene separator
|
T_TEXT = 9 # Text line
|
||||||
T_SKIP = 10 # Paragraph break
|
T_SEP = 10 # Scene separator
|
||||||
T_PBREAK = 11 # Page break
|
T_SKIP = 11 # Paragraph break
|
||||||
|
T_PBREAK = 12 # Page break
|
||||||
|
|
||||||
A_LEFT = 1 # Left aligned
|
A_LEFT = 1 # Left aligned
|
||||||
A_RIGHT = 2 # Right aligned
|
A_RIGHT = 2 # Right aligned
|
||||||
A_CENTRE = 3 # Centred
|
A_CENTRE = 3 # Centred
|
||||||
A_JUSTIFY = 4 # Justified
|
A_JUSTIFY = 4 # Justified
|
||||||
|
|
||||||
def __init__(self, theProject, theParent):
|
def __init__(self, theProject, theParent):
|
||||||
|
|
||||||
@@ -78,8 +79,11 @@ class Tokenizer():
|
|||||||
self.theResult = None # The result text after conversion
|
self.theResult = None # The result text after conversion
|
||||||
|
|
||||||
# User Settings
|
# User Settings
|
||||||
|
self.doBodyText = True # Include body text
|
||||||
|
self.doSynopsis = False # Also process synopsis comments
|
||||||
self.doComments = False # Also process comments
|
self.doComments = False # Also process comments
|
||||||
self.doKeywords = False # Also process keywords like tags and references
|
self.doKeywords = False # Also process keywords like tags and references
|
||||||
|
self.doJustify = False # Justify text
|
||||||
|
|
||||||
self.fmtTitle = "%title%" # Formatting for titles
|
self.fmtTitle = "%title%" # Formatting for titles
|
||||||
self.fmtChapter = "%title%" # Formatting for numbered chapters
|
self.fmtChapter = "%title%" # Formatting for numbered chapters
|
||||||
@@ -113,14 +117,6 @@ class Tokenizer():
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
def setComments(self, doComments):
|
|
||||||
self.doComments = doComments
|
|
||||||
return
|
|
||||||
|
|
||||||
def setKeywords(self, doKeywords):
|
|
||||||
self.doKeywords = doKeywords
|
|
||||||
return
|
|
||||||
|
|
||||||
def setTitleFormat(self, fmtTitle):
|
def setTitleFormat(self, fmtTitle):
|
||||||
self.fmtTitle = fmtTitle
|
self.fmtTitle = fmtTitle
|
||||||
return
|
return
|
||||||
@@ -143,6 +139,26 @@ class Tokenizer():
|
|||||||
self.hideSection = hideSection
|
self.hideSection = hideSection
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def setBodyText(self, doBodyText):
|
||||||
|
self.doBodyText = doBodyText
|
||||||
|
return
|
||||||
|
|
||||||
|
def setSynopsis(self, doSynopsis):
|
||||||
|
self.doSynopsis = doSynopsis
|
||||||
|
return
|
||||||
|
|
||||||
|
def setComments(self, doComments):
|
||||||
|
self.doComments = doComments
|
||||||
|
return
|
||||||
|
|
||||||
|
def setKeywords(self, doKeywords):
|
||||||
|
self.doKeywords = doKeywords
|
||||||
|
return
|
||||||
|
|
||||||
|
def setJustify(self, doJustify):
|
||||||
|
self.doJustify = doJustify
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Class Methods
|
# Class Methods
|
||||||
##
|
##
|
||||||
@@ -207,25 +223,38 @@ class Tokenizer():
|
|||||||
[None, self.FMT_U_B, None, self.FMT_U_E]
|
[None, self.FMT_U_B, None, self.FMT_U_E]
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
if self.doJustify:
|
||||||
|
defAlign = self.A_JUSTIFY
|
||||||
|
else:
|
||||||
|
defAlign = self.A_LEFT
|
||||||
|
|
||||||
self.theTokens = []
|
self.theTokens = []
|
||||||
for aLine in self.theText.splitlines():
|
for aLine in self.theText.splitlines():
|
||||||
|
|
||||||
# Tag lines starting with specific characters
|
# Tag lines starting with specific characters
|
||||||
if len(aLine.strip()) == 0:
|
if len(aLine.strip()) == 0:
|
||||||
self.theTokens.append((self.T_EMPTY,"",None,self.A_LEFT))
|
self.theTokens.append((self.T_EMPTY, "", None, self.A_LEFT))
|
||||||
elif aLine[0] == "%":
|
elif aLine[0] == "%":
|
||||||
self.theTokens.append((self.T_COMMENT,aLine[1:].strip(),None,self.A_LEFT))
|
cLine = aLine[1:].strip()
|
||||||
|
if cLine.lower().startswith("synopsis:"):
|
||||||
|
self.theTokens.append((self.T_SYNOPSIS, cLine[9:].strip(), None, defAlign))
|
||||||
|
else:
|
||||||
|
self.theTokens.append((self.T_COMMENT, aLine[1:].strip(), None, defAlign))
|
||||||
elif aLine[0] == "@":
|
elif aLine[0] == "@":
|
||||||
self.theTokens.append((self.T_KEYWORD,aLine[1:].strip(),None,self.A_LEFT))
|
self.theTokens.append((self.T_KEYWORD, aLine[1:].strip(), None, self.A_LEFT))
|
||||||
elif aLine[:2] == "# ":
|
elif aLine[:2] == "# ":
|
||||||
self.theTokens.append((self.T_HEAD1,aLine[2:].strip(),None,self.A_LEFT))
|
self.theTokens.append((self.T_HEAD1, aLine[2:].strip(), None, self.A_LEFT))
|
||||||
elif aLine[:3] == "## ":
|
elif aLine[:3] == "## ":
|
||||||
self.theTokens.append((self.T_HEAD2,aLine[3:].strip(),None,self.A_LEFT))
|
self.theTokens.append((self.T_HEAD2, aLine[3:].strip(), None, self.A_LEFT))
|
||||||
elif aLine[:4] == "### ":
|
elif aLine[:4] == "### ":
|
||||||
self.theTokens.append((self.T_HEAD3,aLine[4:].strip(),None,self.A_LEFT))
|
self.theTokens.append((self.T_HEAD3, aLine[4:].strip(), None, self.A_LEFT))
|
||||||
elif aLine[:5] == "#### ":
|
elif aLine[:5] == "#### ":
|
||||||
self.theTokens.append((self.T_HEAD4,aLine[5:].strip(),None,self.A_LEFT))
|
self.theTokens.append((self.T_HEAD4, aLine[5:].strip(), None, self.A_LEFT))
|
||||||
else:
|
else:
|
||||||
|
if not self.doBodyText:
|
||||||
|
# Skip all body text
|
||||||
|
continue
|
||||||
|
|
||||||
# Otherwise we use RegEx to find formatting tags within a line of text
|
# Otherwise we use RegEx to find formatting tags within a line of text
|
||||||
fmtPos = []
|
fmtPos = []
|
||||||
for theRX, theKeys in rxFormats:
|
for theRX, theKeys in rxFormats:
|
||||||
@@ -240,11 +269,11 @@ class Tokenizer():
|
|||||||
|
|
||||||
# Save the line as is, but append the array of formatting locations
|
# Save the line as is, but append the array of formatting locations
|
||||||
# sorted by position
|
# sorted by position
|
||||||
fmtPos = sorted(fmtPos,key=itemgetter(0))
|
fmtPos = sorted(fmtPos, key=itemgetter(0))
|
||||||
self.theTokens.append((self.T_TEXT,aLine,fmtPos,self.A_LEFT))
|
self.theTokens.append((self.T_TEXT, aLine, fmtPos, defAlign))
|
||||||
|
|
||||||
# Always add an empty line at the end
|
# Always add an empty line at the end
|
||||||
self.theTokens.append((self.T_EMPTY,"",None,self.A_LEFT))
|
self.theTokens.append((self.T_EMPTY, "", None, self.A_LEFT))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -283,37 +312,37 @@ class Tokenizer():
|
|||||||
if not isUnNum:
|
if not isUnNum:
|
||||||
self.numChapter += 1
|
self.numChapter += 1
|
||||||
tText = self._formatChapter(tText,isUnNum)
|
tText = self._formatChapter(tText,isUnNum)
|
||||||
self.theTokens[n] = (tType,tText,None,self.A_LEFT)
|
self.theTokens[n] = (tType, tText, None, self.A_LEFT)
|
||||||
self.firstScene = True
|
self.firstScene = True
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3:
|
||||||
tTemp = self._formatScene(tText)
|
tTemp = self._formatScene(tText)
|
||||||
if tTemp == "" and self.hideScene:
|
if tTemp == "" and self.hideScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
||||||
elif tTemp == "" and not self.hideScene:
|
elif tTemp == "" and not self.hideScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (self.T_SKIP,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_SKIP, "", None, self.A_LEFT)
|
||||||
elif tTemp == self.fmtScene:
|
elif tTemp == self.fmtScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (self.T_SEP,tTemp,None,self.A_CENTRE)
|
self.theTokens[n] = (self.T_SEP, tTemp, None, self.A_CENTRE)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (tType,tTemp,None,self.A_LEFT)
|
self.theTokens[n] = (tType, tTemp, None, self.A_LEFT)
|
||||||
self.firstScene = False
|
self.firstScene = False
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4:
|
||||||
tTemp = self._formatSection(tText)
|
tTemp = self._formatSection(tText)
|
||||||
if tTemp == "" and self.hideSection:
|
if tTemp == "" and self.hideSection:
|
||||||
self.theTokens[n] = (self.T_EMPTY,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
||||||
elif tTemp == "" and not self.hideSection:
|
elif tTemp == "" and not self.hideSection:
|
||||||
self.theTokens[n] = (self.T_SKIP,"",None,self.A_LEFT)
|
self.theTokens[n] = (self.T_SKIP, "", None, self.A_LEFT)
|
||||||
elif tTemp == self.fmtSection:
|
elif tTemp == self.fmtSection:
|
||||||
self.theTokens[n] = (self.T_SEP,tTemp,None,self.A_CENTRE)
|
self.theTokens[n] = (self.T_SEP, tTemp, None, self.A_CENTRE)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (tType,tTemp,None,self.A_LEFT)
|
self.theTokens[n] = (tType, tTemp, None, self.A_LEFT)
|
||||||
|
|
||||||
# For title page and partitions, we need to centre all text
|
# For title page and partitions, we need to centre all text
|
||||||
# and for some formats, we need a page break
|
# and for some formats, we need a page break
|
||||||
@@ -323,9 +352,9 @@ class Tokenizer():
|
|||||||
tType = tToken[0]
|
tType = tToken[0]
|
||||||
tText = tToken[1]
|
tText = tToken[1]
|
||||||
tFormat = tToken[2]
|
tFormat = tToken[2]
|
||||||
self.theTokens[n] = (tType,tText,tFormat,self.A_CENTRE)
|
self.theTokens[n] = (tType, tText, tFormat, self.A_CENTRE)
|
||||||
|
|
||||||
self.theTokens.append((self.T_PBREAK,"",None,self.A_LEFT))
|
self.theTokens.append((self.T_PBREAK, "", None, self.A_LEFT))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
+113
-13
@@ -42,7 +42,9 @@ 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 nwConst, nwFiles, nwAlert, nwItemType
|
from nw.constants import (
|
||||||
|
nwConst, nwFiles, nwAlert, nwItemType, nwItemLayout, nwItemClass
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -70,11 +72,11 @@ class GuiBuildNovel(QDialog):
|
|||||||
|
|
||||||
self.setWindowTitle("Build Project")
|
self.setWindowTitle("Build Project")
|
||||||
self.setMinimumWidth(800)
|
self.setMinimumWidth(800)
|
||||||
self.setMinimumHeight(700)
|
self.setMinimumHeight(800)
|
||||||
|
|
||||||
self.resize(
|
self.resize(
|
||||||
self.optState.getInt("GuiBuildNovel", "winWidth", 800),
|
self.optState.getInt("GuiBuildNovel", "winWidth", 800),
|
||||||
self.optState.getInt("GuiBuildNovel", "winHeight", 700)
|
self.optState.getInt("GuiBuildNovel", "winHeight", 800)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
@@ -128,6 +130,21 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.titleForm.setColumnStretch(0, 1)
|
self.titleForm.setColumnStretch(0, 1)
|
||||||
self.titleForm.setColumnStretch(1, 0)
|
self.titleForm.setColumnStretch(1, 0)
|
||||||
|
|
||||||
|
# Text Options
|
||||||
|
# =============
|
||||||
|
self.textGroup = QGroupBox("Text Options", self)
|
||||||
|
self.textForm = QGridLayout(self)
|
||||||
|
self.textGroup.setLayout(self.textForm)
|
||||||
|
|
||||||
|
self.justifyText = QSwitch()
|
||||||
|
self.justifyText.setChecked(self.optState.getBool("GuiBuildNovel", "justifyText", False))
|
||||||
|
|
||||||
|
self.textForm.addWidget(QLabel("Justify text"), 0, 0)
|
||||||
|
self.textForm.addWidget(self.justifyText, 0, 1)
|
||||||
|
|
||||||
|
self.textForm.setColumnStretch(0, 1)
|
||||||
|
self.textForm.setColumnStretch(1, 0)
|
||||||
|
|
||||||
# Build Settings
|
# Build Settings
|
||||||
# ==============
|
# ==============
|
||||||
self.buildGroup = QGroupBox("Build Overrides", self)
|
self.buildGroup = QGroupBox("Build Overrides", self)
|
||||||
@@ -156,11 +173,11 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.includeKeywords = QSwitch()
|
self.includeKeywords = QSwitch()
|
||||||
self.includeKeywords.setChecked(self.theProject.titleFormat["withKeywords"])
|
self.includeKeywords.setChecked(self.theProject.titleFormat["withKeywords"])
|
||||||
|
|
||||||
self.includeForm.addWidget(QLabel("Include Synopsis"), 0, 0)
|
self.includeForm.addWidget(QLabel("Include synopsis"), 0, 0)
|
||||||
self.includeForm.addWidget(self.includeSynopsis, 0, 1)
|
self.includeForm.addWidget(self.includeSynopsis, 0, 1)
|
||||||
self.includeForm.addWidget(QLabel("Include Comments"), 1, 0)
|
self.includeForm.addWidget(QLabel("Include comments"), 1, 0)
|
||||||
self.includeForm.addWidget(self.includeComments, 1, 1)
|
self.includeForm.addWidget(self.includeComments, 1, 1)
|
||||||
self.includeForm.addWidget(QLabel("Include Keywords"), 2, 0)
|
self.includeForm.addWidget(QLabel("Include keywords"), 2, 0)
|
||||||
self.includeForm.addWidget(self.includeKeywords, 2, 1)
|
self.includeForm.addWidget(self.includeKeywords, 2, 1)
|
||||||
|
|
||||||
self.includeForm.setColumnStretch(0, 1)
|
self.includeForm.setColumnStretch(0, 1)
|
||||||
@@ -179,11 +196,11 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.ignoreFlag = QSwitch()
|
self.ignoreFlag = QSwitch()
|
||||||
self.ignoreFlag.setChecked(self.optState.getBool("GuiBuildNovel", "ignoreFlag", False))
|
self.ignoreFlag.setChecked(self.optState.getBool("GuiBuildNovel", "ignoreFlag", False))
|
||||||
|
|
||||||
self.addsForm.addWidget(QLabel("Include Novel Files"), 0, 0)
|
self.addsForm.addWidget(QLabel("Include novel files"), 0, 0)
|
||||||
self.addsForm.addWidget(self.novelFiles, 0, 1)
|
self.addsForm.addWidget(self.novelFiles, 0, 1)
|
||||||
self.addsForm.addWidget(QLabel("Include Note Files"), 1, 0)
|
self.addsForm.addWidget(QLabel("Include note files"), 1, 0)
|
||||||
self.addsForm.addWidget(self.noteFiles, 1, 1)
|
self.addsForm.addWidget(self.noteFiles, 1, 1)
|
||||||
self.addsForm.addWidget(QLabel("Ignore Export Flag"), 2, 0)
|
self.addsForm.addWidget(QLabel("Ignore export flag"), 2, 0)
|
||||||
self.addsForm.addWidget(self.ignoreFlag, 2, 1)
|
self.addsForm.addWidget(self.ignoreFlag, 2, 1)
|
||||||
|
|
||||||
self.addsForm.setColumnStretch(0, 1)
|
self.addsForm.setColumnStretch(0, 1)
|
||||||
@@ -245,6 +262,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
# Assemble GUI
|
# Assemble GUI
|
||||||
# ============
|
# ============
|
||||||
self.toolsBox.addWidget(self.titleGroup)
|
self.toolsBox.addWidget(self.titleGroup)
|
||||||
|
self.toolsBox.addWidget(self.textGroup)
|
||||||
self.toolsBox.addWidget(self.buildGroup)
|
self.toolsBox.addWidget(self.buildGroup)
|
||||||
self.toolsBox.addWidget(self.includeGroup)
|
self.toolsBox.addWidget(self.includeGroup)
|
||||||
self.toolsBox.addWidget(self.addsGroup)
|
self.toolsBox.addWidget(self.addsGroup)
|
||||||
@@ -280,11 +298,50 @@ class GuiBuildNovel(QDialog):
|
|||||||
"""Build a preview of the project in the document viewer.
|
"""Build a preview of the project in the document viewer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
makeHtml = ToHtml(self.theProject, self.theParent)
|
# Get Settings
|
||||||
self.htmlText = ""
|
fmtTitle = self.fmtTitle.text().strip()
|
||||||
|
fmtChapter = self.fmtChapter.text().strip()
|
||||||
|
fmtUnnumbered = self.fmtUnnumbered.text().strip()
|
||||||
|
fmtScene = self.fmtScene.text().strip()
|
||||||
|
fmtSection = self.fmtSection.text().strip()
|
||||||
|
justifyText = self.justifyText.isChecked()
|
||||||
|
outlineMode = self.outlineMode.isChecked()
|
||||||
|
incSynopsis = self.includeSynopsis.isChecked()
|
||||||
|
incComments = self.includeComments.isChecked()
|
||||||
|
incKeywords = self.includeKeywords.isChecked()
|
||||||
|
novelFiles = self.novelFiles.isChecked()
|
||||||
|
noteFiles = self.noteFiles.isChecked()
|
||||||
|
ignoreFlag = self.ignoreFlag.isChecked()
|
||||||
|
doBodyText = True
|
||||||
|
|
||||||
for tItem in self.theProject.projTree:
|
if outlineMode:
|
||||||
if tItem is not None and tItem.itemType == nwItemType.FILE:
|
fmtTitle = "%title%"
|
||||||
|
fmtChapter = "Chapter: %title%"
|
||||||
|
fmtUnnumbered = "Chapter: %title%"
|
||||||
|
fmtScene = "Scene: %title%"
|
||||||
|
fmtSection = "Section: %title%"
|
||||||
|
doBodyText = False
|
||||||
|
incSynopsis = True
|
||||||
|
novelFiles = True
|
||||||
|
noteFiles = False
|
||||||
|
|
||||||
|
makeHtml = ToHtml(self.theProject, self.theParent)
|
||||||
|
makeHtml.setTitleFormat(fmtTitle)
|
||||||
|
makeHtml.setChapterFormat(fmtChapter)
|
||||||
|
makeHtml.setUnNumberedFormat(fmtUnnumbered)
|
||||||
|
makeHtml.setSceneFormat(fmtScene, fmtScene == "")
|
||||||
|
makeHtml.setSectionFormat(fmtSection, fmtSection == "")
|
||||||
|
makeHtml.setBodyText(doBodyText)
|
||||||
|
makeHtml.setSynopsis(incSynopsis)
|
||||||
|
makeHtml.setComments(incComments)
|
||||||
|
makeHtml.setKeywords(incKeywords)
|
||||||
|
makeHtml.setJustify(justifyText)
|
||||||
|
|
||||||
|
self.htmlText = ""
|
||||||
|
self.buildProgress.setMaximum(len(self.theProject.projTree))
|
||||||
|
self.buildProgress.setValue(0)
|
||||||
|
for nItt, tItem in enumerate(self.theProject.projTree):
|
||||||
|
if self._checkInclude(tItem, noteFiles, novelFiles, ignoreFlag):
|
||||||
makeHtml.setText(tItem.itemHandle)
|
makeHtml.setText(tItem.itemHandle)
|
||||||
makeHtml.doAutoReplace()
|
makeHtml.doAutoReplace()
|
||||||
makeHtml.tokenizeText()
|
makeHtml.tokenizeText()
|
||||||
@@ -292,11 +349,49 @@ class GuiBuildNovel(QDialog):
|
|||||||
makeHtml.doConvert()
|
makeHtml.doConvert()
|
||||||
makeHtml.doPostProcessing()
|
makeHtml.doPostProcessing()
|
||||||
self.htmlText += makeHtml.getResult()
|
self.htmlText += makeHtml.getResult()
|
||||||
|
self.buildProgress.setValue(nItt+1)
|
||||||
|
|
||||||
self.docView.setHtml(self.htmlText)
|
self.docView.setHtml(self.htmlText)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _checkInclude(self, theItem, noteFiles, novelFiles, ignoreFlag):
|
||||||
|
"""This function checks whether a file should be included in the
|
||||||
|
export or not. For standard note and novel files, this is
|
||||||
|
controlled by the options selected by the user. For other files
|
||||||
|
classified as non-exportable, a few checks must be made, and the
|
||||||
|
following are not:
|
||||||
|
* Items that are not actual files.
|
||||||
|
* Items that have been orphaned which are tagged as NO_LAYOUT
|
||||||
|
and NO_CLASS.
|
||||||
|
* Items that appear in the TRASH folder or have parent set to
|
||||||
|
None (orphaned files).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if theItem is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not theItem.isExported and not ignoreFlag:
|
||||||
|
return False
|
||||||
|
|
||||||
|
isNone = theItem.itemType != nwItemType.FILE
|
||||||
|
isNone |= theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||||
|
isNone |= theItem.itemClass == nwItemClass.NO_CLASS
|
||||||
|
isNone |= theItem.itemClass == nwItemClass.TRASH
|
||||||
|
isNone |= theItem.parHandle == self.theProject.projTree.trashRoot()
|
||||||
|
isNone |= theItem.parHandle is None
|
||||||
|
isNote = theItem.itemLayout == nwItemLayout.NOTE
|
||||||
|
isNovel = not isNone and not isNote
|
||||||
|
|
||||||
|
if isNone:
|
||||||
|
return False
|
||||||
|
if isNote and not noteFiles:
|
||||||
|
return False
|
||||||
|
if isNovel and not novelFiles:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def _saveDocument(self, theFormat):
|
def _saveDocument(self, theFormat):
|
||||||
"""Save the document to various formats.
|
"""Save the document to various formats.
|
||||||
"""
|
"""
|
||||||
@@ -474,6 +569,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
# GUI Settings
|
# GUI Settings
|
||||||
self.optState.setValue("GuiBuildNovel", "winWidth", self.width())
|
self.optState.setValue("GuiBuildNovel", "winWidth", self.width())
|
||||||
self.optState.setValue("GuiBuildNovel", "winHeight", self.height())
|
self.optState.setValue("GuiBuildNovel", "winHeight", self.height())
|
||||||
|
self.optState.setValue("GuiBuildNovel", "justifyText", self.justifyText.isChecked())
|
||||||
self.optState.setValue("GuiBuildNovel", "outlineMode", self.outlineMode.isChecked())
|
self.optState.setValue("GuiBuildNovel", "outlineMode", self.outlineMode.isChecked())
|
||||||
self.optState.setValue("GuiBuildNovel", "addNovel", self.novelFiles.isChecked())
|
self.optState.setValue("GuiBuildNovel", "addNovel", self.novelFiles.isChecked())
|
||||||
self.optState.setValue("GuiBuildNovel", "addNotes", self.noteFiles.isChecked())
|
self.optState.setValue("GuiBuildNovel", "addNotes", self.noteFiles.isChecked())
|
||||||
@@ -557,6 +653,10 @@ class GuiBuildNovelDocView(QTextBrowser):
|
|||||||
"mark {"
|
"mark {"
|
||||||
" background-color: rgb(240, 198, 116);"
|
" background-color: rgb(240, 198, 116);"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
".tags {"
|
||||||
|
" color: rgb(245, 135, 31);"
|
||||||
|
" font-wright: bold;"
|
||||||
|
"}\n"
|
||||||
)
|
)
|
||||||
self.qDocument.setDefaultStyleSheet(styleSheet)
|
self.qDocument.setDefaultStyleSheet(styleSheet)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="240" autoCount="28" timeStamp="2020-05-10 21:26:54">
|
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="257" autoCount="31" timeStamp="2020-05-10 22:50:38">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</autoReplace>
|
</autoReplace>
|
||||||
<titleFormat>
|
<titleFormat>
|
||||||
<title>%title%</title>
|
<title>%title%</title>
|
||||||
<chapter>Chapter %num%\\%title%</chapter>
|
<chapter>Chapter %num%.\\%title%</chapter>
|
||||||
<unnumbered>%title%</unnumbered>
|
<unnumbered>%title%</unnumbered>
|
||||||
<scene>* * *</scene>
|
<scene>* * *</scene>
|
||||||
<section></section>
|
<section></section>
|
||||||
|
|||||||
Reference in New Issue
Block a user