Complete the manuscript build dialog, and the doc builder class

This commit is contained in:
Veronica Berglyd Olsen
2023-06-09 21:07:46 +02:00
parent 8b7aab36a2
commit 5f4b6009ce
10 changed files with 225 additions and 82 deletions
+82 -40
View File
@@ -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