Merge branch 'dev' into view_details
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
<h1>Help!</h1>
|
||||
<p><i>A brief guide to make the most out of the Build Novel Project tool.</i></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 for instance 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> – This is replaced with the text you put in your headings in your
|
||||
documents</p>
|
||||
<p><mark>%chnum%</mark> – This is replaced with the chapter number of your chapter type
|
||||
headings. These are generated automaticall starting from 1, but ignoring chapter headings in
|
||||
files with "Unnumbered" layout.</p>
|
||||
<p><mark>%chnumword%</mark> – This is replaced with the chapter number, but instead of an
|
||||
arabic number, the word for it is used, e.g. One, Two, Fifteen, Twenty-Five, etc.</p>
|
||||
<p><mark>%scnum%</mark> – This is replaced with the scene number. The number is reset to one
|
||||
for each new chapter, so it is the scene number within the current chapter.</p>
|
||||
<p><mark>%scabsnum%</mark> – This is replaced with the absolute scene number. That is, the
|
||||
number is counted from the first scene in the novel, and not reset for each chapter.</p>
|
||||
<p><mark>\\</mark> – Two backslashes are replaced by a line break.</p>
|
||||
<p><b>Note:</b> The Scene and Section formats are treated slightly differently than the other title
|
||||
formats. If the format is a constant text, that is, contains no <mark>%keyword%</mark> tags, it
|
||||
will be treated as a separator instead. Scene and Section separators are centred, and for
|
||||
scenes, not shown if placed directly after the chapter heading. For instance, it you want the
|
||||
classic three asterisk <mark>* * *</mark> separator between scenes, just put that into the
|
||||
scene format box, and nothing else.</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>
|
||||
+8
-27
@@ -37,8 +37,6 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class NWDoc():
|
||||
|
||||
FILE_MN = "main.nwd"
|
||||
|
||||
def __init__(self, theProject, theParent):
|
||||
|
||||
self.mainConf = nw.CONFIG
|
||||
@@ -93,8 +91,9 @@ class NWDoc():
|
||||
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
||||
self.docEditable = False
|
||||
|
||||
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
|
||||
self.fileLoc = path.join(docDir,docFile)
|
||||
docDir = "content"
|
||||
docFile = self.docHandle+".nwd"
|
||||
self.fileLoc = path.join(docDir, docFile)
|
||||
logger.debug("Opening document %s" % self.fileLoc)
|
||||
dataDir = path.join(self.theProject.projPath, docDir)
|
||||
docPath = path.join(dataDir, docFile)
|
||||
@@ -139,8 +138,9 @@ class NWDoc():
|
||||
if self.docHandle is None or not self.docEditable:
|
||||
return False
|
||||
|
||||
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
|
||||
logger.debug("Saving document %s" % path.join(docDir,docFile))
|
||||
docDir = "content"
|
||||
docFile = self.docHandle+".nwd"
|
||||
logger.debug("Saving document %s" % path.join(docDir, docFile))
|
||||
dataPath = path.join(self.theProject.projPath, docDir)
|
||||
docPath = path.join(dataPath, docFile)
|
||||
if not path.isdir(dataPath):
|
||||
@@ -159,12 +159,6 @@ class NWDoc():
|
||||
self.makeAlert(["Could not save document.",str(e)], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
# Remove bak files from old file save method, if one exists
|
||||
# This part can eventually be removed
|
||||
docBack = path.join(dataPath, docFile[:-3]+"bak")
|
||||
if path.isfile(docBack):
|
||||
unlink(docBack)
|
||||
|
||||
# If we're here, the file was successfully saved, so we can
|
||||
# replace the temp file with the actual file
|
||||
if path.isfile(docPath):
|
||||
@@ -179,7 +173,8 @@ class NWDoc():
|
||||
"""Permanently delete a document source file and its backups
|
||||
from the project data folder.
|
||||
"""
|
||||
docDir, docFile = self._assemblePath(tHandle, self.FILE_MN)
|
||||
docDir = "content"
|
||||
docFile = self.docHandle+".nwd"
|
||||
dataPath = path.join(self.theProject.projPath, docDir)
|
||||
chkList = []
|
||||
chkList.append(path.join(dataPath, docFile))
|
||||
@@ -226,18 +221,4 @@ class NWDoc():
|
||||
|
||||
return theMeta, thePath
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
@staticmethod
|
||||
def _assemblePath(tHandle, docExt):
|
||||
"""Assemble the file path for a given handle.
|
||||
"""
|
||||
if tHandle is None:
|
||||
return None, None
|
||||
docDir = "data_"+tHandle[0]
|
||||
docFile = tHandle[1:13]+"_"+docExt
|
||||
return docDir, docFile
|
||||
|
||||
# END Class NWDoc
|
||||
|
||||
+104
-25
@@ -33,7 +33,7 @@
|
||||
import logging
|
||||
import nw
|
||||
|
||||
from os import path, mkdir, listdir, unlink, rename
|
||||
from os import path, mkdir, listdir, unlink, rename, rmdir
|
||||
from lxml import etree
|
||||
from hashlib import sha256
|
||||
from time import time
|
||||
@@ -74,6 +74,7 @@ class NWProject():
|
||||
# Class Settings
|
||||
self.projPath = None # The full path to where the currently open project is saved
|
||||
self.projMeta = None # The full path to the project's meta data folder
|
||||
self.projData = None # The full path to the project's data folder
|
||||
self.projDict = None # The spell check dictionary
|
||||
self.projFile = None # The file name of the project main XML file
|
||||
|
||||
@@ -195,6 +196,7 @@ class NWProject():
|
||||
# Project Settings
|
||||
self.projPath = None
|
||||
self.projMeta = None
|
||||
self.projData = None
|
||||
self.projDict = None
|
||||
self.projFile = nwFiles.PROJ_FILE
|
||||
self.projName = ""
|
||||
@@ -247,10 +249,13 @@ class NWProject():
|
||||
logger.debug("Opening project: %s" % self.projPath)
|
||||
|
||||
self.projMeta = path.join(self.projPath,"meta")
|
||||
self.projData = path.join(self.projPath,"content")
|
||||
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
||||
|
||||
if not self._checkFolder(self.projMeta):
|
||||
return False
|
||||
if not self._checkFolder(self.projData):
|
||||
return False
|
||||
|
||||
if overrideLock:
|
||||
self._clearLockFile()
|
||||
@@ -291,7 +296,7 @@ class NWProject():
|
||||
self.clearProject()
|
||||
return False
|
||||
|
||||
xRoot = nwXML.getroot()
|
||||
xRoot = nwXML.getroot()
|
||||
nwxRoot = xRoot.tag
|
||||
|
||||
appVersion = "Unknown"
|
||||
@@ -314,13 +319,40 @@ class NWProject():
|
||||
logger.verbose("XML root is %s" % nwxRoot)
|
||||
logger.verbose("File version is %s" % fileVersion)
|
||||
|
||||
if not nwxRoot == "novelWriterXML" or not fileVersion == "1.0":
|
||||
# Check File Type
|
||||
# ===============
|
||||
if not nwxRoot == "novelWriterXML":
|
||||
self.makeAlert(
|
||||
"Project file does not appear to be a novelWriterXML file version 1.0",
|
||||
"Project file does not appear to be a novelWriterXML file.",
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
# Check Project Storage Version
|
||||
# =============================
|
||||
if fileVersion == "1.0":
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(self.theParent, "Old Project Version", (
|
||||
"The project file and data is created by a %s version lower than 0.7. "
|
||||
"Do you want to upgrade the project to the most recent format?<br><br>"
|
||||
"Note that after the upgrade, you cannot open the project with an older "
|
||||
"version of novelWriter any more, so make sure you have a recent backup."
|
||||
) % nw.__package__)
|
||||
if msgRes == QMessageBox.Yes:
|
||||
self._updateStorage()
|
||||
else:
|
||||
return False
|
||||
elif fileVersion != "1.1":
|
||||
self.makeAlert((
|
||||
"Unknown or unsupported %s project format. "
|
||||
"The project cannot be opened by this version of %s."
|
||||
) % (
|
||||
nw.__package__, nw.__package__
|
||||
), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
# Check novelWriter Version
|
||||
# =========================
|
||||
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
||||
@@ -333,6 +365,8 @@ class NWProject():
|
||||
if msgRes != QMessageBox.Yes:
|
||||
return False
|
||||
|
||||
# Start Parsing XML
|
||||
# =================
|
||||
for xChild in xRoot:
|
||||
if xChild.tag == "project":
|
||||
logger.debug("Found project meta")
|
||||
@@ -404,16 +438,21 @@ class NWProject():
|
||||
file.
|
||||
"""
|
||||
if self.projPath is None:
|
||||
self.makeAlert("Project path not set, cannot save.", nwAlert.ERROR)
|
||||
self.makeAlert(
|
||||
"Project path not set, cannot save project.", nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
|
||||
self.projMeta = path.join(self.projPath,"meta")
|
||||
self.projMeta = path.join(self.projPath, "meta")
|
||||
self.projData = path.join(self.projPath, "content")
|
||||
saveTime = time()
|
||||
|
||||
if not self._checkFolder(self.projPath):
|
||||
return False
|
||||
if not self._checkFolder(self.projMeta):
|
||||
return False
|
||||
if not self._checkFolder(self.projData):
|
||||
return False
|
||||
|
||||
logger.debug("Saving project: %s" % self.projPath)
|
||||
|
||||
@@ -427,7 +466,7 @@ class NWProject():
|
||||
nwXML = etree.Element("novelWriterXML",attrib={
|
||||
"appVersion" : str(nw.__version__),
|
||||
"hexVersion" : str(nw.__hexversion__),
|
||||
"fileVersion" : "1.0",
|
||||
"fileVersion" : "1.1",
|
||||
"saveCount" : str(self.saveCount),
|
||||
"autoCount" : str(self.autoCount),
|
||||
"timeStamp" : formatTimeStamp(saveTime),
|
||||
@@ -937,29 +976,20 @@ class NWProject():
|
||||
if self.projPath is None:
|
||||
return
|
||||
|
||||
# First, scan the project data folders
|
||||
itemList = []
|
||||
for subItem in listdir(self.projPath):
|
||||
if subItem[:5] != "data_":
|
||||
continue
|
||||
dataDir = path.join(self.projPath,subItem)
|
||||
for subFile in listdir(dataDir):
|
||||
if subFile[-4:] == ".nwd":
|
||||
newItem = path.join(subItem,subFile)
|
||||
itemList.append(newItem)
|
||||
|
||||
# Then check the valid files
|
||||
# Then check the files in the data folder
|
||||
orphanFiles = []
|
||||
for fileItem in itemList:
|
||||
if len(fileItem) != 28:
|
||||
# Just to be safe, shouldn't happen
|
||||
for fileItem in listdir(self.projData):
|
||||
if not fileItem.endswith(".nwd"):
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
fHandle = fileItem[5]+fileItem[7:19]
|
||||
if len(fileItem) != 17:
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
fHandle = fileItem[:13]
|
||||
if fHandle in self.projTree:
|
||||
logger.debug("Checking file %s, handle %s: OK" % (fileItem,fHandle))
|
||||
logger.debug("Checking file %s, handle %s: OK" % (fileItem, fHandle))
|
||||
else:
|
||||
logger.debug("Checking file %s, handle %s: Orphaned" % (fileItem,fHandle))
|
||||
logger.debug("Checking file %s, handle %s: Orphaned" % (fileItem, fHandle))
|
||||
orphanFiles.append(fHandle)
|
||||
|
||||
# Report status
|
||||
@@ -1016,6 +1046,55 @@ class NWProject():
|
||||
|
||||
return True
|
||||
|
||||
def _updateStorage(self):
|
||||
"""Updates the project storage folder from 1.0 to 1.1.
|
||||
"""
|
||||
contDir = path.join(self.projPath, "content")
|
||||
self._checkFolder(contDir)
|
||||
errList = []
|
||||
|
||||
for projItem in listdir(self.projPath):
|
||||
itemPath = path.join(self.projPath, projItem)
|
||||
if not path.isdir(itemPath) or not projItem.startswith("data_"):
|
||||
continue
|
||||
for dataFile in listdir(itemPath):
|
||||
dataPath = path.join(itemPath, dataFile)
|
||||
if dataFile.endswith(".bak"):
|
||||
try:
|
||||
unlink(dataPath)
|
||||
logger.info("Deleted file: %s" % dataPath)
|
||||
except:
|
||||
errList.append("Failed to delete: %s" % dataPath)
|
||||
|
||||
elif dataFile.endswith(".nwd") and len(dataFile) == 21:
|
||||
tHandle = projItem[-1]+dataFile[:12]
|
||||
newPath = path.join(contDir, tHandle+".nwd")
|
||||
try:
|
||||
rename(dataPath, newPath)
|
||||
logger.info("Moved file: %s" % dataPath)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except:
|
||||
errList.append("Failed to move: %s" % dataPath)
|
||||
|
||||
else:
|
||||
newPath = path.join(self.projPath, "unknown_"+dataFile)
|
||||
try:
|
||||
rename(dataPath, newPath)
|
||||
logger.info("Moved file: %s" % dataPath)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except:
|
||||
errList.append("Failed to move: %s" % dataPath)
|
||||
try:
|
||||
rmdir(itemPath)
|
||||
logger.info("Removed folder: %s" % itemPath)
|
||||
except:
|
||||
errList.append("Failed to delete: %s" % itemPath)
|
||||
|
||||
if errList:
|
||||
self.makeAlert(errList, nwAlert.ERROR)
|
||||
|
||||
return
|
||||
|
||||
# END Class NWProject
|
||||
|
||||
# ================================================================================================ #
|
||||
|
||||
@@ -577,10 +577,10 @@ class Tokenizer():
|
||||
"""Replaces the %keyword% strings.
|
||||
"""
|
||||
theTitle = theTitle.replace(r"%title%", theText)
|
||||
theTitle = theTitle.replace(r"%chnum%", str(self.numChapter))
|
||||
theTitle = theTitle.replace(r"%scnum%", str(self.numChScene))
|
||||
theTitle = theTitle.replace(r"%scabsnum%", str(self.numAbsScene))
|
||||
theTitle = theTitle.replace(r"%chnumword%", numberToWord(self.numChapter,"en"))
|
||||
theTitle = theTitle.replace(r"%ch%", str(self.numChapter))
|
||||
theTitle = theTitle.replace(r"%sc%", str(self.numChScene))
|
||||
theTitle = theTitle.replace(r"%sca%", str(self.numAbsScene))
|
||||
theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter,"en"))
|
||||
return theTitle
|
||||
|
||||
# END Class Tokenizer
|
||||
|
||||
+1
-6
@@ -89,7 +89,7 @@ def projectMaintenance(theProject):
|
||||
if path.isdir(theProject.projPath):
|
||||
cacheDir = path.join(theProject.projPath, "cache")
|
||||
if path.isdir(cacheDir):
|
||||
logger.info("Deprecated cache folder found")
|
||||
logger.info("Deprecated cache folder content found")
|
||||
rmList = []
|
||||
for i in range(10):
|
||||
rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
|
||||
@@ -101,11 +101,6 @@ def projectMaintenance(theProject):
|
||||
unlink(rmFile)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
logger.info("Deleting: %s" % cacheDir)
|
||||
try:
|
||||
rmdir(cacheDir)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
|
||||
# Remove no longer used meta files
|
||||
rmList = []
|
||||
|
||||
+77
-34
@@ -39,7 +39,7 @@ from PyQt5.QtGui import (
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTextBrowser, QPushButton, QLabel,
|
||||
QLineEdit, QGroupBox, QGridLayout, QProgressBar, QMenu, QAction,
|
||||
QFileDialog, QFontComboBox, QSpinBox
|
||||
QFileDialog, QFontComboBox, QSpinBox, QDialogButtonBox
|
||||
)
|
||||
|
||||
from nw.gui.additions import QSwitch
|
||||
@@ -75,11 +75,11 @@ class GuiBuildNovel(QDialog):
|
||||
self.nwdText = [] # List of markdown documents
|
||||
|
||||
self.setWindowTitle("Build Novel Project")
|
||||
self.setMinimumWidth(800)
|
||||
self.setMinimumWidth(900)
|
||||
self.setMinimumHeight(800)
|
||||
|
||||
self.resize(
|
||||
self.optState.getInt("GuiBuildNovel", "winWidth", 800),
|
||||
self.optState.getInt("GuiBuildNovel", "winWidth", 900),
|
||||
self.optState.getInt("GuiBuildNovel", "winHeight", 800)
|
||||
)
|
||||
|
||||
@@ -95,30 +95,61 @@ class GuiBuildNovel(QDialog):
|
||||
self.titleForm = QGridLayout(self)
|
||||
self.titleGroup.setLayout(self.titleForm)
|
||||
|
||||
fmtHelp = (
|
||||
r"<b>Formatting Codes:</b><br>"
|
||||
r"%title% for the title as set in the document<br>"
|
||||
r"%ch% for chapter number (1, 2, 3)<br>"
|
||||
r"%chw% for chapter number as a word (one, two)<br>"
|
||||
r"%sc% for scene number within chapter<br>"
|
||||
r"%sca% for scene number within novel"
|
||||
)
|
||||
fmtScHelp = (
|
||||
r"<br><br>"
|
||||
r"Leave blank to skip this heading, or set to a static text, like "
|
||||
r"for instance '* * *', to make a separator. The separator will "
|
||||
r"be centred automatically and only appear between sections of "
|
||||
r"the same type."
|
||||
)
|
||||
|
||||
self.fmtTitle = QLineEdit()
|
||||
self.fmtTitle.setMaxLength(200)
|
||||
self.fmtTitle.setFixedWidth(200)
|
||||
self.fmtTitle.setText(self.theProject.titleFormat["title"])
|
||||
self.fmtTitle.setFixedWidth(220)
|
||||
self.fmtTitle.setToolTip(fmtHelp)
|
||||
self.fmtTitle.setText(
|
||||
self._reFmtCodes(self.theProject.titleFormat["title"])
|
||||
)
|
||||
|
||||
self.fmtChapter = QLineEdit()
|
||||
self.fmtChapter.setMaxLength(200)
|
||||
self.fmtChapter.setFixedWidth(200)
|
||||
self.fmtChapter.setText(self.theProject.titleFormat["chapter"])
|
||||
self.fmtChapter.setFixedWidth(220)
|
||||
self.fmtChapter.setToolTip(fmtHelp)
|
||||
self.fmtChapter.setText(
|
||||
self._reFmtCodes(self.theProject.titleFormat["chapter"])
|
||||
)
|
||||
|
||||
self.fmtUnnumbered = QLineEdit()
|
||||
self.fmtUnnumbered.setMaxLength(200)
|
||||
self.fmtUnnumbered.setFixedWidth(200)
|
||||
self.fmtUnnumbered.setText(self.theProject.titleFormat["unnumbered"])
|
||||
self.fmtUnnumbered.setFixedWidth(220)
|
||||
self.fmtUnnumbered.setToolTip(fmtHelp)
|
||||
self.fmtUnnumbered.setText(
|
||||
self._reFmtCodes(self.theProject.titleFormat["unnumbered"])
|
||||
)
|
||||
|
||||
self.fmtScene = QLineEdit()
|
||||
self.fmtScene.setMaxLength(200)
|
||||
self.fmtScene.setFixedWidth(200)
|
||||
self.fmtScene.setText(self.theProject.titleFormat["scene"])
|
||||
self.fmtScene.setFixedWidth(220)
|
||||
self.fmtScene.setToolTip(fmtHelp + fmtScHelp)
|
||||
self.fmtScene.setText(
|
||||
self._reFmtCodes(self.theProject.titleFormat["scene"])
|
||||
)
|
||||
|
||||
self.fmtSection = QLineEdit()
|
||||
self.fmtSection.setMaxLength(200)
|
||||
self.fmtSection.setFixedWidth(200)
|
||||
self.fmtSection.setText(self.theProject.titleFormat["section"])
|
||||
self.fmtSection.setFixedWidth(220)
|
||||
self.fmtSection.setToolTip(fmtHelp + fmtScHelp)
|
||||
self.fmtSection.setText(
|
||||
self._reFmtCodes(self.theProject.titleFormat["section"])
|
||||
)
|
||||
|
||||
self.titleForm.addWidget(QLabel("Title"), 0, 0, 1, 1, Qt.AlignLeft)
|
||||
self.titleForm.addWidget(self.fmtTitle, 0, 1, 1, 1, Qt.AlignRight)
|
||||
@@ -141,7 +172,8 @@ class GuiBuildNovel(QDialog):
|
||||
self.textGroup.setLayout(self.textForm)
|
||||
|
||||
self.textFont = QFontComboBox()
|
||||
self.textFont.setFixedWidth(200)
|
||||
self.textFont.setFixedWidth(220)
|
||||
self.textFont.setToolTip("The font is used for PDF and printing. Other formats have no font set.")
|
||||
self.textFont.setCurrentFont(
|
||||
QFont(self.optState.getString("GuiBuildNovel", "textFont", self.mainConf.textFont))
|
||||
)
|
||||
@@ -151,11 +183,13 @@ class GuiBuildNovel(QDialog):
|
||||
self.textSize.setMinimum(5)
|
||||
self.textSize.setMaximum(48)
|
||||
self.textSize.setSingleStep(1)
|
||||
self.textSize.setToolTip("The size is used for PDF and printing. Other formats have no size set.")
|
||||
self.textSize.setValue(
|
||||
self.optState.getInt("GuiBuildNovel", "textSize", self.mainConf.textSize)
|
||||
)
|
||||
|
||||
self.justifyText = QSwitch()
|
||||
self.justifyText.setToolTip("Applies to PDF, printing, HTML, and Open Document exports.")
|
||||
self.justifyText.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "justifyText", False)
|
||||
)
|
||||
@@ -177,12 +211,15 @@ class GuiBuildNovel(QDialog):
|
||||
self.includeGroup.setLayout(self.includeForm)
|
||||
|
||||
self.includeSynopsis = QSwitch()
|
||||
self.includeSynopsis.setToolTip("Include synopsis type comments in the output.")
|
||||
self.includeSynopsis.setChecked(self.theProject.titleFormat["withSynopsis"])
|
||||
|
||||
self.includeComments = QSwitch()
|
||||
self.includeComments.setToolTip("Include plain comments in the output.")
|
||||
self.includeComments.setChecked(self.theProject.titleFormat["withComments"])
|
||||
|
||||
self.includeKeywords = QSwitch()
|
||||
self.includeKeywords.setToolTip("Include meta keywords (tags, references) in the output.")
|
||||
self.includeKeywords.setChecked(self.theProject.titleFormat["withKeywords"])
|
||||
|
||||
self.includeForm.addWidget(QLabel("Include synopsis"), 0, 0, 1, 1, Qt.AlignLeft)
|
||||
@@ -202,21 +239,34 @@ class GuiBuildNovel(QDialog):
|
||||
self.addsGroup.setLayout(self.addsForm)
|
||||
|
||||
self.novelFiles = QSwitch()
|
||||
self.novelFiles.setToolTip(
|
||||
"Include files with layouts 'Book', 'Page', 'Partition', "
|
||||
"'Chapter', 'Unnumbered', and 'Scene'."
|
||||
)
|
||||
self.novelFiles.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "addNovel", True)
|
||||
)
|
||||
|
||||
self.noteFiles = QSwitch()
|
||||
self.noteFiles.setToolTip("Include files with layout 'Note'.")
|
||||
self.noteFiles.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "addNotes", False)
|
||||
)
|
||||
|
||||
self.ignoreFlag = QSwitch()
|
||||
self.ignoreFlag.setToolTip(
|
||||
"Ignore the 'Include when building project' setting and include "
|
||||
"all files in the output."
|
||||
)
|
||||
self.ignoreFlag.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "ignoreFlag", False)
|
||||
)
|
||||
|
||||
self.excludeBody = QSwitch()
|
||||
self.excludeBody.setToolTip(
|
||||
"Exclude body text in the output. Combine with 'Include synopsis' "
|
||||
"for making outline."
|
||||
)
|
||||
self.excludeBody.setChecked(
|
||||
self.optState.getBool("GuiBuildNovel", "excludeBody", False)
|
||||
)
|
||||
@@ -279,13 +329,12 @@ class GuiBuildNovel(QDialog):
|
||||
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
||||
self.saveMenu.addAction(self.saveTXT)
|
||||
|
||||
self.btnClose = QPushButton("Close")
|
||||
self.btnClose.clicked.connect(self._doClose)
|
||||
|
||||
self.buttonForm.addWidget(self.btnHelp, 0, 0)
|
||||
self.buttonForm.addWidget(self.btnSave, 0, 0)
|
||||
self.buttonForm.addWidget(self.btnPrint, 0, 1)
|
||||
self.buttonForm.addWidget(self.btnSave, 1, 0)
|
||||
self.buttonForm.addWidget(self.btnClose, 1, 1)
|
||||
|
||||
# Buttons
|
||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
self.buttonBox.rejected.connect(self._doClose)
|
||||
|
||||
# Assemble GUI
|
||||
# ============
|
||||
@@ -303,6 +352,7 @@ class GuiBuildNovel(QDialog):
|
||||
self.innerBox.addWidget(self.docView)
|
||||
|
||||
self.outerBox.addLayout(self.innerBox)
|
||||
self.outerBox.addWidget(self.buttonBox)
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
self.innerBox.setStretch(0, 0)
|
||||
@@ -661,21 +711,14 @@ class GuiBuildNovel(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def _showHelp(self):
|
||||
"""Generate a help text and show it in the document window.
|
||||
def _reFmtCodes(self, theFormat):
|
||||
"""Translates old formatting codes to new ones.
|
||||
"""
|
||||
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.setStyleSheet()
|
||||
self.docView.setContent(helpText)
|
||||
else:
|
||||
self.theParent.makeAlert(
|
||||
"Could not open help text file for Build Project.", nwAlert.ERROR
|
||||
)
|
||||
return
|
||||
theFormat = theFormat.replace(r"%chnum%", r"%ch%")
|
||||
theFormat = theFormat.replace(r"%scnum%", r"%sc%")
|
||||
theFormat = theFormat.replace(r"%scabsnum%", r"%sca%")
|
||||
theFormat = theFormat.replace(r"%chnumword%", r"%chw%")
|
||||
return theFormat
|
||||
|
||||
# END Class GuiBuildNovel
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ class GuiProjectLoad(QDialog):
|
||||
self.lblRecent = QLabel("<b>Recently Opened Projects</b>")
|
||||
self.lblPath = QLabel("<b>Path</b>")
|
||||
self.selPath = QLineEdit("")
|
||||
self.selPath.setEnabled(False)
|
||||
self.selPath.setReadOnly(True)
|
||||
|
||||
self.browseButton = QPushButton("...")
|
||||
self.browseButton.setMaximumWidth(30)
|
||||
|
||||
Reference in New Issue
Block a user