Complete the manuscript build dialog, and the doc builder class
This commit is contained in:
@@ -32,7 +32,7 @@ from PyQt5.QtGui import QFont, QFontInfo
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwBuildFmt
|
||||
from novelwriter.error import formatException
|
||||
from novelwriter.error import formatException, logException
|
||||
from novelwriter.core.tomd import ToMarkdown
|
||||
from novelwriter.core.toodt import ToOdt
|
||||
from novelwriter.core.tohtml import ToHtml
|
||||
@@ -110,13 +110,13 @@ class NWBuildDocument:
|
||||
def iterBuild(self, path: Path, bFormat: nwBuildFmt) -> Iterable[tuple[int, bool]]:
|
||||
"""Wrapper for builders based on format."""
|
||||
if bFormat in (nwBuildFmt.ODT, nwBuildFmt.FODT):
|
||||
yield from self.iterBuildOpenDocument(path, bFormat == "fodt")
|
||||
yield from self.iterBuildOpenDocument(path, bFormat == nwBuildFmt.FODT)
|
||||
elif bFormat in (nwBuildFmt.HTML, nwBuildFmt.J_HTML):
|
||||
yield from self.iterBuildHTML(path if bFormat == "html" else None)
|
||||
yield from self.iterBuildHTML(path, asJson=bFormat == nwBuildFmt.J_HTML)
|
||||
elif bFormat in (nwBuildFmt.STD_MD, nwBuildFmt.EXT_MD):
|
||||
yield from self.iterBuildMarkdown(path, bFormat == "md+")
|
||||
yield from self.iterBuildMarkdown(path, bFormat == nwBuildFmt.EXT_MD)
|
||||
elif bFormat in (nwBuildFmt.NWD, nwBuildFmt.J_NWD):
|
||||
yield from self.iterBuildNovelWriter(path if bFormat == "nwd" else None)
|
||||
yield from self.iterBuildNWD(path, asJson=bFormat == nwBuildFmt.J_NWD)
|
||||
return
|
||||
|
||||
def iterBuildOpenDocument(self, path: Path, isFlat: bool) -> Iterable[tuple[int, bool]]:
|
||||
@@ -143,11 +143,12 @@ class NWBuildDocument:
|
||||
else:
|
||||
makeObj.saveOpenDocText(path)
|
||||
except Exception as exc:
|
||||
logException()
|
||||
self._error = formatException(exc)
|
||||
|
||||
return
|
||||
|
||||
def iterBuildHTML(self, path: Path | None) -> Iterable[tuple[int, bool]]:
|
||||
def iterBuildHTML(self, path: Path | None, asJson: bool = False) -> Iterable[tuple[int, bool]]:
|
||||
"""Build an HTML file. If path is None, no file is saved. This
|
||||
is used for generating build previews.
|
||||
"""
|
||||
@@ -169,8 +170,12 @@ class NWBuildDocument:
|
||||
|
||||
if isinstance(path, Path):
|
||||
try:
|
||||
makeObj.saveHTML5(path)
|
||||
if asJson:
|
||||
makeObj.saveHtmlJson(path)
|
||||
else:
|
||||
makeObj.saveHtml5(path)
|
||||
except Exception as exc:
|
||||
logException()
|
||||
self._error = formatException(exc)
|
||||
|
||||
return
|
||||
@@ -201,11 +206,12 @@ class NWBuildDocument:
|
||||
try:
|
||||
makeObj.saveMarkdown(path)
|
||||
except Exception as exc:
|
||||
logException()
|
||||
self._error = formatException(exc)
|
||||
|
||||
return
|
||||
|
||||
def iterBuildNovelWriter(self, path: Path | None) -> Iterable[tuple[int, bool]]:
|
||||
def iterBuildNWD(self, path: Path | None, asJson: bool = False) -> Iterable[tuple[int, bool]]:
|
||||
"""Build a novelWriter Markdown file."""
|
||||
makeObj = ToMarkdown(self._project)
|
||||
filtered = self._setupBuild(makeObj)
|
||||
@@ -226,8 +232,12 @@ class NWBuildDocument:
|
||||
|
||||
if isinstance(path, Path):
|
||||
try:
|
||||
makeObj.saveRawMarkdown(path)
|
||||
if asJson:
|
||||
makeObj.saveRawMarkdownJSON(path)
|
||||
else:
|
||||
makeObj.saveRawMarkdown(path)
|
||||
except Exception as exc:
|
||||
logException()
|
||||
self._error = formatException(exc)
|
||||
|
||||
return
|
||||
|
||||
+35
-18
@@ -23,11 +23,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from time import time
|
||||
from pathlib import Path
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.common import formatTimeStamp
|
||||
from novelwriter.constants import nwKeyWords, nwLabels, nwHtmlUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
||||
@@ -296,38 +299,52 @@ class ToHtml(Tokenizer):
|
||||
|
||||
return
|
||||
|
||||
def saveHTML5(self, savePath: str | Path):
|
||||
"""Save the data to an .html file.
|
||||
"""
|
||||
with open(savePath, mode="w", encoding="utf-8") as outFile:
|
||||
theStyle = self.getStyleSheet()
|
||||
theStyle.append("article {width: 800px; margin: 40px auto;}")
|
||||
bodyText = "".join(self._fullHTML)
|
||||
bodyText = bodyText.replace("\t", "	").rstrip()
|
||||
|
||||
theHtml = (
|
||||
def saveHtml5(self, path: str | Path):
|
||||
"""Save the data to an HTML file."""
|
||||
with open(path, mode="w", encoding="utf-8") as fObj:
|
||||
fObj.write((
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<meta charset='utf-8'>\n"
|
||||
"<title>{projTitle:s}</title>\n"
|
||||
"<title>{title:s}</title>\n"
|
||||
"</head>\n"
|
||||
"<style>\n"
|
||||
"{htmlStyle:s}\n"
|
||||
"{style:s}\n"
|
||||
"</style>\n"
|
||||
"<body>\n"
|
||||
"<article>\n"
|
||||
"{bodyText:s}\n"
|
||||
"{body:s}\n"
|
||||
"</article>\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
).format(
|
||||
projTitle=self._project.data.name,
|
||||
htmlStyle="\n".join(theStyle),
|
||||
bodyText=bodyText,
|
||||
)
|
||||
outFile.write(theHtml)
|
||||
title=self._project.data.name,
|
||||
style="\n".join(self.getStyleSheet()),
|
||||
body=("".join(self._fullHTML)).replace("\t", "	").rstrip(),
|
||||
))
|
||||
logger.info("Wrote file: %s", path)
|
||||
return
|
||||
|
||||
def saveHtmlJson(self, path: str | Path):
|
||||
"""Save the data to a JSON file."""
|
||||
timeStamp = time()
|
||||
data = {
|
||||
"meta": {
|
||||
"projectName": self._project.data.name,
|
||||
"novelTitle": self._project.data.title,
|
||||
"novelAuthor": self._project.data.author,
|
||||
"buildTime": int(timeStamp),
|
||||
"buildTimeStr": formatTimeStamp(timeStamp),
|
||||
},
|
||||
"text": {
|
||||
"css": self.getStyleSheet(),
|
||||
"html": [page.rstrip("\n").split("\n") for page in self.fullHTML],
|
||||
}
|
||||
}
|
||||
with open(path, mode="w", encoding="utf-8") as fObj:
|
||||
json.dump(data, fObj, indent=2)
|
||||
logger.info("Wrote file: %s", path)
|
||||
return
|
||||
|
||||
def replaceTabs(self, nSpaces: int = 8, spaceChar: str = " "):
|
||||
|
||||
@@ -25,9 +25,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import json
|
||||
import logging
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from time import time
|
||||
from pathlib import Path
|
||||
from operator import itemgetter
|
||||
from functools import partial
|
||||
@@ -35,7 +37,7 @@ from functools import partial
|
||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||
|
||||
from novelwriter.enum import nwItemLayout, nwItemType
|
||||
from novelwriter.common import numberToRoman, checkInt
|
||||
from novelwriter.common import formatTimeStamp, numberToRoman, checkInt
|
||||
from novelwriter.constants import nwConst, nwHeadFmt, nwRegEx, nwUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
|
||||
@@ -740,13 +742,32 @@ class Tokenizer(ABC):
|
||||
|
||||
return True
|
||||
|
||||
def saveRawMarkdown(self, savePath: str | Path):
|
||||
"""Save the data to a plain text file."""
|
||||
with open(savePath, mode="w", encoding="utf-8") as outFile:
|
||||
def saveRawMarkdown(self, path: str | Path):
|
||||
"""Save the raw text to a plain text file."""
|
||||
with open(path, mode="w", encoding="utf-8") as outFile:
|
||||
for nwdPage in self._allMarkdown:
|
||||
outFile.write(nwdPage)
|
||||
return
|
||||
|
||||
def saveRawMarkdownJSON(self, path: str | Path):
|
||||
"""Save the raw text to a JSON file."""
|
||||
timeStamp = time()
|
||||
data = {
|
||||
"meta": {
|
||||
"projectName": self._project.data.name,
|
||||
"novelTitle": self._project.data.title,
|
||||
"novelAuthor": self._project.data.author,
|
||||
"buildTime": int(timeStamp),
|
||||
"buildTimeStr": formatTimeStamp(timeStamp),
|
||||
},
|
||||
"text": {
|
||||
"nwd": [page.rstrip("\n").split("\n") for page in self._allMarkdown],
|
||||
}
|
||||
}
|
||||
with open(path, mode="w", encoding="utf-8") as fObj:
|
||||
json.dump(data, fObj, indent=2)
|
||||
return
|
||||
|
||||
# END Class Tokenizer
|
||||
|
||||
|
||||
@@ -760,27 +781,23 @@ class HeadingFormatter:
|
||||
return
|
||||
|
||||
def incChapter(self):
|
||||
"""Increment the chapter counter.
|
||||
"""
|
||||
"""Increment the chapter counter."""
|
||||
self._chCount += 1
|
||||
return
|
||||
|
||||
def incScene(self):
|
||||
"""Increment the scene counters.
|
||||
"""
|
||||
"""Increment the scene counters."""
|
||||
self._scChCount += 1
|
||||
self._scAbsCount += 1
|
||||
return
|
||||
|
||||
def resetScene(self):
|
||||
"""Reset the chapter scene counter.
|
||||
"""
|
||||
"""Reset the chapter scene counter."""
|
||||
self._scChCount = 0
|
||||
return
|
||||
|
||||
def apply(self, hFormat: str, text: str):
|
||||
"""Apply formatting to a specific heading.
|
||||
"""
|
||||
"""Apply formatting to a specific heading."""
|
||||
hFormat = hFormat.replace(nwHeadFmt.TITLE, text)
|
||||
hFormat = hFormat.replace(nwHeadFmt.CH_NUM, str(self._chCount))
|
||||
hFormat = hFormat.replace(nwHeadFmt.SC_NUM, str(self._scChCount))
|
||||
|
||||
@@ -179,6 +179,7 @@ class ToMarkdown(Tokenizer):
|
||||
"""Save the data to a plain text file."""
|
||||
with open(path, mode="w", encoding="utf-8") as outFile:
|
||||
outFile.write("".join(self._fullMD))
|
||||
logger.info("Wrote file: %s", path)
|
||||
return
|
||||
|
||||
def replaceTabs(self, nSpaces: int = 8, spaceChar: str = " "):
|
||||
|
||||
@@ -501,6 +501,7 @@ class ToOdt(Tokenizer):
|
||||
xml = ET.ElementTree(self._dFlat)
|
||||
xmlIndent(xml)
|
||||
xml.write(fObj, encoding="utf-8", xml_declaration=True)
|
||||
logger.info("Wrote file: %s", path)
|
||||
return
|
||||
|
||||
def saveOpenDocText(self, path: str | Path):
|
||||
@@ -535,6 +536,8 @@ class ToOdt(Tokenizer):
|
||||
putInZip("meta.xml", self._dMeta, outZip)
|
||||
putInZip("styles.xml", self._dStyl, outZip)
|
||||
|
||||
logger.info("Wrote file: %s", path)
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
@@ -21,6 +21,7 @@ General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from math import ceil
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
novelWriter – Custom Widget: Progress Simple
|
||||
============================================
|
||||
|
||||
File History:
|
||||
Created: 2023-06-09 [2.1b1]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from math import ceil
|
||||
|
||||
from PyQt5.QtGui import QPaintEvent, QPainter
|
||||
from PyQt5.QtWidgets import QProgressBar, QWidget
|
||||
|
||||
|
||||
class NProgressSimple(QProgressBar):
|
||||
"""Extension: Simple Progress Widget
|
||||
|
||||
A custom widget that paints a plain bar with no other styling.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: QWidget):
|
||||
super().__init__(parent=parent)
|
||||
return
|
||||
|
||||
def paintEvent(self, event: QPaintEvent):
|
||||
"""Custom painter for the progress bar."""
|
||||
if self.value() == 0:
|
||||
return
|
||||
progress = ceil(self.width()*float(self.value())/self.maximum())
|
||||
qPaint = QPainter(self)
|
||||
qPaint.setRenderHint(QPainter.Antialiasing, True)
|
||||
qPaint.setPen(self.palette().highlight().color())
|
||||
qPaint.setBrush(self.palette().highlight())
|
||||
qPaint.drawRect(0, 0, progress, self.height())
|
||||
return
|
||||
|
||||
# END Class NProgressSimple
|
||||
@@ -24,24 +24,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5.QtCore import QSize, Qt, pyqtSlot
|
||||
from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog,
|
||||
QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem,
|
||||
QProgressBar, QPushButton, QSplitter, QVBoxLayout, QWidget
|
||||
QPushButton, QSplitter, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwBuildFmt
|
||||
from novelwriter.enum import nwAlert, nwBuildFmt
|
||||
from novelwriter.common import makeFileNameSafe
|
||||
from novelwriter.constants import nwLabels
|
||||
from novelwriter.core.item import NWItem
|
||||
from novelwriter.core.docbuild import NWBuildDocument
|
||||
from novelwriter.core.buildsettings import BuildSettings
|
||||
from novelwriter.extensions.simpleprogress import NProgressSimple
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from novelwriter.guimain import GuiMain
|
||||
@@ -50,7 +51,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuiManuscriptBuild(QDialog):
|
||||
"""GUI Tools: Manucript Builder Dialog
|
||||
"""GUI Tools: Manuscript Build Dialog
|
||||
|
||||
This is the tool for running the build itself. It can be accessed
|
||||
independently of the Manuscript Build Tool.
|
||||
@@ -73,10 +74,13 @@ class GuiManuscriptBuild(QDialog):
|
||||
|
||||
self.setWindowTitle(self.tr("Build Manuscript"))
|
||||
self.setMinimumWidth(CONFIG.pxInt(500))
|
||||
self.setMinimumHeight(CONFIG.pxInt(250))
|
||||
self.setMinimumHeight(CONFIG.pxInt(300))
|
||||
|
||||
iPx = self.mainTheme.baseIconSize
|
||||
wWin = CONFIG.pxInt(660)
|
||||
sp4 = CONFIG.pxInt(4)
|
||||
sp8 = CONFIG.pxInt(8)
|
||||
sp16 = CONFIG.pxInt(16)
|
||||
wWin = CONFIG.pxInt(620)
|
||||
hWin = CONFIG.pxInt(360)
|
||||
|
||||
pOptions = self.theProject.options
|
||||
@@ -141,35 +145,42 @@ class GuiManuscriptBuild(QDialog):
|
||||
self.lblMain.setWordWrap(True)
|
||||
self.lblMain.setFont(font)
|
||||
|
||||
# Build Path
|
||||
self.lblPath = QLabel(self.tr("Path"))
|
||||
self.buildPath = QLineEdit(self)
|
||||
self.btnBrowse = QPushButton(self.mainTheme.getIcon("browse"), "")
|
||||
|
||||
self.pathBox = QHBoxLayout()
|
||||
self.pathBox.addWidget(self.buildPath)
|
||||
self.pathBox.addWidget(self.btnBrowse)
|
||||
self.pathBox.setSpacing(sp8)
|
||||
|
||||
# Build Name
|
||||
self.lblName = QLabel(self.tr("File Name"))
|
||||
self.buildName = QLineEdit()
|
||||
self.buildName = QLineEdit(self)
|
||||
self.btnReset = QPushButton(self.mainTheme.getIcon("revert"), "")
|
||||
self.btnReset.setToolTip(self.tr("Reset file name to default"))
|
||||
|
||||
self.nameBox = QHBoxLayout()
|
||||
self.nameBox.addWidget(self.buildName)
|
||||
self.nameBox.addWidget(self.btnReset)
|
||||
self.nameBox.setSpacing(sp8)
|
||||
|
||||
# Build Progress
|
||||
self.lblProgress = QLabel(self.tr("Progress"))
|
||||
|
||||
self.buildProgress = QProgressBar()
|
||||
self.buildProgress = NProgressSimple(self)
|
||||
self.buildProgress.setMinimum(0)
|
||||
self.buildProgress.setValue(0)
|
||||
|
||||
self.progressBox = QVBoxLayout()
|
||||
self.progressBox.addWidget(self.lblProgress)
|
||||
self.progressBox.addWidget(self.buildProgress)
|
||||
self.progressBox.setSpacing(CONFIG.pxInt(4))
|
||||
self.buildProgress.setTextVisible(False)
|
||||
self.buildProgress.setFixedHeight(sp8)
|
||||
|
||||
# Build Box
|
||||
self.buildBox = QGridLayout()
|
||||
self.buildBox.addWidget(self.lblName, 1, 0)
|
||||
self.buildBox.addLayout(self.nameBox, 1, 1)
|
||||
self.buildBox.addWidget(self.lblProgress, 2, 0)
|
||||
self.buildBox.addWidget(self.buildProgress, 2, 1)
|
||||
self.buildBox.setVerticalSpacing(CONFIG.pxInt(4))
|
||||
self.buildBox.addWidget(self.lblPath, 0, 0)
|
||||
self.buildBox.addLayout(self.pathBox, 0, 1)
|
||||
self.buildBox.addWidget(self.lblName, 1, 0)
|
||||
self.buildBox.addLayout(self.nameBox, 1, 1)
|
||||
self.buildBox.setHorizontalSpacing(sp8)
|
||||
self.buildBox.setVerticalSpacing(sp4)
|
||||
|
||||
# Dialog Buttons
|
||||
self.btnBuild = QPushButton(self.mainTheme.getIcon("export"), self.tr("&Build"))
|
||||
@@ -182,7 +193,7 @@ class GuiManuscriptBuild(QDialog):
|
||||
self.mainSplit = QSplitter()
|
||||
self.mainSplit.addWidget(self.formatWidget)
|
||||
self.mainSplit.addWidget(self.contentWidget)
|
||||
self.mainSplit.setHandleWidth(CONFIG.pxInt(16))
|
||||
self.mainSplit.setHandleWidth(sp16)
|
||||
self.mainSplit.setCollapsible(0, False)
|
||||
self.mainSplit.setCollapsible(1, False)
|
||||
self.mainSplit.setSizes([
|
||||
@@ -192,15 +203,21 @@ class GuiManuscriptBuild(QDialog):
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addWidget(self.lblMain, 0, Qt.AlignCenter)
|
||||
self.outerBox.addSpacing(sp16)
|
||||
self.outerBox.addWidget(self.mainSplit, 1)
|
||||
self.outerBox.addSpacing(sp4)
|
||||
self.outerBox.addWidget(self.buildProgress, 0)
|
||||
self.outerBox.addSpacing(sp4)
|
||||
self.outerBox.addLayout(self.buildBox, 0)
|
||||
self.outerBox.addSpacing(sp16)
|
||||
self.outerBox.addWidget(self.dlgButtons, 0)
|
||||
self.outerBox.setSpacing(CONFIG.pxInt(12))
|
||||
self.outerBox.setSpacing(0)
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
self.btnBuild.setFocus()
|
||||
self._populateContentList()
|
||||
self.buildPath.setText(str(self._build.lastPath))
|
||||
if self._build.lastBuildName:
|
||||
self.buildName.setText(self._build.lastBuildName)
|
||||
else:
|
||||
@@ -208,6 +225,7 @@ class GuiManuscriptBuild(QDialog):
|
||||
|
||||
# Signals
|
||||
self.btnReset.clicked.connect(self._doResetBuildName)
|
||||
self.btnBrowse.clicked.connect(self._doSelectPath)
|
||||
self.dlgButtons.clicked.connect(self._dialogButtonClicked)
|
||||
self.listFormats.itemSelectionChanged.connect(self._formatSelectionChanged)
|
||||
|
||||
@@ -253,6 +271,18 @@ class GuiManuscriptBuild(QDialog):
|
||||
self.close()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _doSelectPath(self):
|
||||
"""Select a folder for output."""
|
||||
bPath = Path(self.buildPath.text())
|
||||
bPath = bPath if bPath.is_dir() else self._build.lastPath
|
||||
savePath = QFileDialog.getExistingDirectory(
|
||||
self, self.tr("Select Folder"), str(bPath)
|
||||
)
|
||||
if savePath:
|
||||
self.buildPath.setText(savePath)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _doResetBuildName(self):
|
||||
"""Generate a default build name."""
|
||||
@@ -269,43 +299,55 @@ class GuiManuscriptBuild(QDialog):
|
||||
self.buildProgress.setValue(0)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _resetProgress(self):
|
||||
"""Set the progress bar back to 0."""
|
||||
self.buildProgress.setValue(0)
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _runBuild(self) -> bool:
|
||||
"""Run the currently selected build."""
|
||||
selFormat = self._getSelectedFormat()
|
||||
if not isinstance(selFormat, nwBuildFmt):
|
||||
bFormat = self._getSelectedFormat()
|
||||
if not isinstance(bFormat, nwBuildFmt):
|
||||
return False
|
||||
|
||||
lastName = self.buildName.text().strip()
|
||||
if not lastName:
|
||||
bName = self.buildName.text().strip()
|
||||
if not bName:
|
||||
self._doResetBuildName()
|
||||
|
||||
lastPath = self._build.lastPath
|
||||
selExt = nwLabels.BUILD_EXT[selFormat]
|
||||
selName = Path(makeFileNameSafe(lastName)).with_suffix(selExt)
|
||||
bName = self.buildName.text().strip()
|
||||
|
||||
self.buildProgress.setValue(0)
|
||||
savePath, _ = QFileDialog.getSaveFileName(
|
||||
self, self.tr("Save Manuscript As"), str(lastPath / selName)
|
||||
)
|
||||
if not savePath:
|
||||
bPath = Path(self.buildPath.text())
|
||||
if not bPath.is_dir():
|
||||
self.mainGui.makeAlert(self.tr("Output folder does not exist."), nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
buildPath = Path(savePath)
|
||||
bExt = nwLabels.BUILD_EXT[bFormat]
|
||||
buildPath = (bPath / makeFileNameSafe(bName)).with_suffix(bExt)
|
||||
|
||||
if buildPath.exists():
|
||||
if not self.mainGui.askQuestion(
|
||||
self.tr("File Exists"),
|
||||
self.tr("The file already exists. Do you want to overwrite it?")
|
||||
):
|
||||
return False
|
||||
|
||||
docBuild = NWBuildDocument(self.theProject, self._build)
|
||||
docBuild.queueAll()
|
||||
|
||||
self.buildProgress.setMaximum(len(docBuild))
|
||||
for i, _ in docBuild.iterBuild(buildPath, selFormat):
|
||||
for i, _ in docBuild.iterBuild(buildPath, bFormat):
|
||||
self.buildProgress.setValue(i+1)
|
||||
|
||||
self._build.setLastFormat(selFormat)
|
||||
self._build.setLastPath(buildPath.parent)
|
||||
self._build.setLastBuildName(lastName)
|
||||
self._build.setLastPath(bPath)
|
||||
self._build.setLastBuildName(bName)
|
||||
self._build.setLastFormat(bFormat)
|
||||
|
||||
QTimer.singleShot(1000, self._resetProgress)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ a {color: rgb(66, 113, 174);}
|
||||
.break {text-align: left;}
|
||||
.synopsis {font-style: italic;}
|
||||
.comment {font-style: italic; color: rgb(100, 100, 100);}
|
||||
article {width: 800px; margin: 40px auto;}
|
||||
</style>
|
||||
<body>
|
||||
<article>
|
||||
|
||||
@@ -517,7 +517,6 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
|
||||
# ==========
|
||||
|
||||
theStyle = theHtml.getStyleSheet()
|
||||
theStyle.append("article {width: 800px; margin: 40px auto;}")
|
||||
htmlDoc = (
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
@@ -540,7 +539,7 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
|
||||
)
|
||||
|
||||
saveFile = fncPath / "outFile.htm"
|
||||
theHtml.saveHTML5(saveFile)
|
||||
theHtml.saveHtml5(saveFile)
|
||||
assert readFile(saveFile) == htmlDoc
|
||||
|
||||
# END Test testCoreToHtml_Complex
|
||||
|
||||
Reference in New Issue
Block a user