Merge pull request #82 from vkbo/pandoc_support

Pandoc Export
This commit is contained in:
Veronica K. Berglyd Olsen
2019-10-28 20:50:16 +01:00
committed by GitHub
8 changed files with 322 additions and 97 deletions
+1
View File
@@ -37,6 +37,7 @@ class LaTeXFile(TextFile):
self.outFile = open(filePath,mode="wt+",encoding="utf8") self.outFile = open(filePath,mode="wt+",encoding="utf8")
self.outFile.write("\\documentclass[12pt]{report}\n") self.outFile.write("\\documentclass[12pt]{report}\n")
self.outFile.write("\\usepackage[utf8]{inputenc}\n") self.outFile.write("\\usepackage[utf8]{inputenc}\n")
self.outFile.write("\\usepackage[T1]{fontenc}\n")
self.outFile.write("\n") self.outFile.write("\n")
self.outFile.write("\\begin{document}\n") self.outFile.write("\\begin{document}\n")
except Exception as e: except Exception as e:
+7 -7
View File
@@ -39,7 +39,7 @@ class TextFile():
self.makeAlert = self.theParent.makeAlert self.makeAlert = self.theParent.makeAlert
self.setComments(False) self.setComments(False)
self.setMeta(False) self.setKeywords(False)
self.setWordWrap(80) self.setWordWrap(80)
return return
@@ -60,8 +60,8 @@ class TextFile():
self.theConv.setComments(doComments) self.theConv.setComments(doComments)
return return
def setMeta(self, doMeta): def setKeywords(self, doKeywords):
self.theConv.setCommands(doMeta) self.theConv.setKeywords(doKeywords)
return return
def setWordWrap(self, wordWrap): def setWordWrap(self, wordWrap):
@@ -83,12 +83,12 @@ class TextFile():
self.theConv.setUnNumberedFormat(fmtUnNum) self.theConv.setUnNumberedFormat(fmtUnNum)
return return
def setSceneFormat(self, fmtScene): def setSceneFormat(self, fmtScene, hideScene):
self.theConv.setSceneFormat(fmtScene) self.theConv.setSceneFormat(fmtScene, hideScene)
return return
def setSectionFormat(self, fmtSection): def setSectionFormat(self, fmtSection, hideSection):
self.theConv.setSectionFormat(fmtSection) self.theConv.setSectionFormat(fmtSection, hideSection)
return return
## ##
+6 -3
View File
@@ -83,7 +83,10 @@ class ToHtml(Tokenizer):
self.theResult += "<h4%s>%s</h4>\n" % (hStyle,tText) self.theResult += "<h4%s>%s</h4>\n" % (hStyle,tText)
elif tType == self.T_SEP: elif tType == self.T_SEP:
self.theResult += "<div%s>%s</div>\n" % (hStyle,tText) self.theResult += "<p%s>%s</p>\n" % (hStyle,tText)
elif tType == self.T_SKIP:
self.theResult += "<p>&nbsp;</p>\n"
elif tType == self.T_TEXT: elif tType == self.T_TEXT:
tTemp = tText tTemp = tText
@@ -94,8 +97,8 @@ class ToHtml(Tokenizer):
elif tType == self.T_COMMENT and self.doComments: elif tType == self.T_COMMENT and self.doComments:
self.theResult += "<div class='comment'>%s</div>\n" % tText self.theResult += "<div class='comment'>%s</div>\n" % tText
elif tType == self.T_COMMAND and self.doCommands: elif tType == self.T_KEYWORD and self.doKeywords:
self.theResult += "<pre>%s</pre>\n" % tText self.theResult += "<pre>@%s</pre>\n" % tText
# print(self.theResult) # print(self.theResult)
+5 -1
View File
@@ -90,6 +90,10 @@ class ToLaTeX(Tokenizer):
self.theResult += "%s\n" % self._escapeUnicode(tText) self.theResult += "%s\n" % self._escapeUnicode(tText)
self.theResult += endText self.theResult += endText
elif tType == self.T_SKIP:
self.theResult += "\\bigskip\n"
self.theResult += "\\bigskip\n\n"
elif tType == self.T_TEXT: elif tType == self.T_TEXT:
thisPar.append(self._escapeUnicode(tText)) thisPar.append(self._escapeUnicode(tText))
@@ -99,7 +103,7 @@ class ToLaTeX(Tokenizer):
elif tType == self.T_COMMENT and self.doComments: elif tType == self.T_COMMENT and self.doComments:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
elif tType == self.T_COMMAND and self.doCommands: elif tType == self.T_KEYWORD and self.doKeywords:
self.theResult += "%% @%s\n\n" % tText self.theResult += "%% @%s\n\n" % tText
return return
+4 -1
View File
@@ -98,13 +98,16 @@ class ToMarkdown(Tokenizer):
elif tType == self.T_SEP: elif tType == self.T_SEP:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
elif tType == self.T_SKIP:
self.theResult += "\n\n\n\n"
elif tType == self.T_TEXT: elif tType == self.T_TEXT:
thisPar.append(tText) thisPar.append(tText)
elif tType == self.T_COMMENT and self.doComments: elif tType == self.T_COMMENT and self.doComments:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
elif tType == self.T_COMMAND and self.doCommands: elif tType == self.T_KEYWORD and self.doKeywords:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
return return
+4 -1
View File
@@ -105,13 +105,16 @@ class ToText(Tokenizer):
tText = self._centreText(tText,self.wordWrap) tText = self._centreText(tText,self.wordWrap)
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
elif tType == self.T_SEP:
self.theResult += "\n\n\n\n"
elif tType == self.T_TEXT: elif tType == self.T_TEXT:
thisPar.append(tText) thisPar.append(tText)
elif tType == self.T_COMMENT and self.doComments: elif tType == self.T_COMMENT and self.doComments:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
elif tType == self.T_COMMAND and self.doCommands: elif tType == self.T_KEYWORD and self.doKeywords:
self.theResult += "%s\n\n" % tText self.theResult += "%s\n\n" % tText
return return
+41 -30
View File
@@ -35,14 +35,15 @@ class Tokenizer():
T_EMPTY = 1 # Empty line (new paragraph) T_EMPTY = 1 # Empty line (new paragraph)
T_COMMENT = 2 # Comment line T_COMMENT = 2 # Comment line
T_COMMAND = 3 # Command line T_KEYWORD = 3 # Command line
T_HEAD1 = 4 # Header 1 (title) T_HEAD1 = 4 # Header 1 (title)
T_HEAD2 = 5 # Header 2 (chapter) T_HEAD2 = 5 # Header 2 (chapter)
T_HEAD3 = 6 # Header 3 (scene) T_HEAD3 = 6 # Header 3 (scene)
T_HEAD4 = 7 # Header 4 T_HEAD4 = 7 # Header 4
T_TEXT = 8 # Text line T_TEXT = 8 # Text line
T_SEP = 9 # Scene separator T_SEP = 9 # Scene separator
T_PBREAK = 10 # Page break T_SKIP = 10 # Paragraph break
T_PBREAK = 11 # Page break
A_LEFT = 1 # Left aligned A_LEFT = 1 # Left aligned
A_RIGHT = 2 # Right aligned A_RIGHT = 2 # Right aligned
@@ -51,30 +52,31 @@ class Tokenizer():
def __init__(self, theProject, theParent): def __init__(self, theProject, theParent):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theProject = theProject self.theProject = theProject
self.theParent = theParent self.theParent = theParent
self.theText = None self.theText = None
self.theHandle = None self.theHandle = None
self.theItem = None self.theItem = None
self.theTokens = None self.theTokens = None
self.theResult = None self.theResult = None
self.wordWrap = 80 self.wordWrap = 80
self.doComments = False self.doComments = False
self.doCommands = False self.doKeywords = False
self.fmtTitle = "%title%" self.fmtTitle = "%title%"
self.fmtChapter = "Chapter %numword%: %title%" self.fmtChapter = "Chapter %numword%: %title%"
self.fmtUnNum = "%title%" self.fmtUnNum = "%title%"
self.fmtScene = "* * *" self.fmtScene = "* * *"
self.fmtSection = "%title%" self.fmtSection = "%title%"
self.noSection = True self.hideScene = False
self.hideSection = False
self.numChapter = 0 self.numChapter = 0
self.firstScene = False self.firstScene = False
return return
@@ -86,8 +88,8 @@ class Tokenizer():
self.doComments = doComments self.doComments = doComments
return return
def setCommands(self, doCommands): def setKeywords(self, doKeywords):
self.doCommands = doCommands self.doKeywords = doKeywords
return return
def setWordWrap(self, wordWrap): def setWordWrap(self, wordWrap):
@@ -109,12 +111,14 @@ class Tokenizer():
self.fmtUnNum = fmtUnNum self.fmtUnNum = fmtUnNum
return return
def setSceneFormat(self, fmtScene): def setSceneFormat(self, fmtScene, hideScene):
self.fmtScene = fmtScene self.fmtScene = fmtScene
self.hideScene = hideScene
return return
def setSectionFormat(self, fmtSection): def setSectionFormat(self, fmtSection, hideSection):
self.fmtSection = fmtSection self.fmtSection = fmtSection
self.hideSection = hideSection
return return
## ##
@@ -175,7 +179,7 @@ class Tokenizer():
elif aLine[0] == "%": elif aLine[0] == "%":
self.theTokens.append((self.T_COMMENT,aLine[1:].strip(),None,self.A_LEFT)) self.theTokens.append((self.T_COMMENT,aLine[1:].strip(),None,self.A_LEFT))
elif aLine[0] == "@": elif aLine[0] == "@":
self.theTokens.append((self.T_COMMAND,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] == "## ":
@@ -242,8 +246,13 @@ class Tokenizer():
elif tType == self.T_HEAD3: elif tType == self.T_HEAD3:
tTemp = self._doFormatScene(tText) tTemp = self._doFormatScene(tText)
if tTemp == "": 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:
if self.firstScene:
self.theTokens[n] = (self.T_EMPTY,"",None,self.A_LEFT)
else:
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)
@@ -255,8 +264,10 @@ class Tokenizer():
elif tType == self.T_HEAD4: elif tType == self.T_HEAD4:
tTemp = self._doFormatSection(tText) tTemp = self._doFormatSection(tText)
if tTemp == "": 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:
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:
+254 -54
View File
@@ -20,7 +20,7 @@ from PyQt5.QtCore import Qt, QSize
from PyQt5.QtSvg import QSvgWidget from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QWidget, QTabWidget, QGridLayout, QGroupBox, QCheckBox, QDialog, QHBoxLayout, QVBoxLayout, QWidget, QTabWidget, QGridLayout, QGroupBox, QCheckBox,
QLabel, QComboBox, QLineEdit, QPushButton, QFileDialog, QProgressBar, QSpinBox QLabel, QComboBox, QLineEdit, QPushButton, QFileDialog, QProgressBar, QSpinBox, QMessageBox
) )
from nw.project.document import NWDoc from nw.project.document import NWDoc
@@ -60,9 +60,11 @@ class GuiExport(QDialog):
self.theProject.countStatus() self.theProject.countStatus()
self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState) self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState)
self.tabPandoc = GuiExportPandoc(self.theParent, self.theProject, self.optState)
self.tabWidget = QTabWidget() self.tabWidget = QTabWidget()
self.tabWidget.addTab(self.tabMain, "Settings") self.tabWidget.addTab(self.tabMain, "Settings")
self.tabWidget.addTab(self.tabPandoc, "Pandoc")
self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop) self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox) self.outerBox.addLayout(self.innerBox)
@@ -107,13 +109,21 @@ class GuiExport(QDialog):
eFormat = self.tabMain.outputFormat.currentData() eFormat = self.tabMain.outputFormat.currentData()
fixWidth = self.tabMain.fixedWidth.value() fixWidth = self.tabMain.fixedWidth.value()
wComments = self.tabMain.expComments.isChecked() wComments = self.tabMain.expComments.isChecked()
wKeywords = self.tabMain.expKeywords.isChecked()
chFormat = self.tabMain.chapterFormat.text() chFormat = self.tabMain.chapterFormat.text()
unFormat = self.tabMain.unnumFormat.text() unFormat = self.tabMain.unnumFormat.text()
scFormat = self.tabMain.sceneFormat.text() scFormat = self.tabMain.sceneFormat.text()
seFormat = self.tabMain.sectionFormat.text() seFormat = self.tabMain.sectionFormat.text()
saveTo = self.tabMain.exportPath.text() saveTo = self.tabMain.exportPath.text()
hScene = self.tabMain.hideScene.isChecked()
hSection = self.tabMain.hideSection.isChecked()
pFormat = self.tabPandoc.outputFormat.currentData()
tFormat = GuiExportPandoc.FMT_VIA[pFormat]
nItems = len(self.theProject.treeOrder) nItems = len(self.theProject.treeOrder)
if eFormat == GuiExportMain.FMT_PDOC:
nItems += int(0.2*nItems)
self.exportProgress.setMinimum(0) self.exportProgress.setMinimum(0)
self.exportProgress.setMaximum(nItems) self.exportProgress.setMaximum(nItems)
self.exportProgress.setValue(0) self.exportProgress.setValue(0)
@@ -133,19 +143,25 @@ class GuiExport(QDialog):
outFile = LaTeXFile(self.theProject, self.theParent) outFile = LaTeXFile(self.theProject, self.theParent)
elif eFormat == GuiExportMain.FMT_NWD: elif eFormat == GuiExportMain.FMT_NWD:
outFile = ConcatFile(self.theProject, self.theParent) outFile = ConcatFile(self.theProject, self.theParent)
elif eFormat == GuiExportMain.FMT_PDOC:
if tFormat == "html":
outFile = HtmlFile(self.theProject, self.theParent)
elif tFormat == "markdown":
outFile = MarkdownFile(self.theProject, self.theParent)
if outFile is None: if outFile is None:
return False return False
if outFile.openFile(saveTo): if outFile.openFile(saveTo):
outFile.setComments(wComments) outFile.setComments(wComments)
outFile.setKeywords(wKeywords)
outFile.setExportNovel(wNovel) outFile.setExportNovel(wNovel)
outFile.setExportNotes(wNotes) outFile.setExportNotes(wNotes)
outFile.setWordWrap(fixWidth) outFile.setWordWrap(fixWidth)
outFile.setChapterFormat(chFormat) outFile.setChapterFormat(chFormat)
outFile.setUnNumberedFormat(unFormat) outFile.setUnNumberedFormat(unFormat)
outFile.setSceneFormat(scFormat) outFile.setSceneFormat(scFormat, hScene)
outFile.setSectionFormat(seFormat) outFile.setSectionFormat(seFormat, hSection)
else: else:
self.exportStatus.setText("Failed to open file for writing ...") self.exportStatus.setText("Failed to open file for writing ...")
return False return False
@@ -180,33 +196,111 @@ class GuiExport(QDialog):
"Make sure the python package 'latexcodec' is installed and working." "Make sure the python package 'latexcodec' is installed and working."
), nwAlert.WARN) ), nwAlert.WARN)
return if eFormat != GuiExportMain.FMT_PDOC:
return True
# If we've reached this point, we're also running Pandoc
if self._callPandoc(tFormat, pFormat):
self.exportProgress.setValue(nItems)
self.exportStatus.setText("Pandoc conversion complete")
logger.verbose("Pandoc conversion complete")
else:
self.exportProgress.setValue(nItems)
self.exportStatus.setText("Pandoc conversion failed")
logger.verbose("Pandoc conversion failed")
return False
return True
def _callPandoc(self, inFmt, outFmt):
pFmt = {
GuiExportPandoc.FMT_ODT : "odt",
GuiExportPandoc.FMT_DOCX : "docx",
GuiExportPandoc.FMT_EPUB2 : "epub2",
GuiExportPandoc.FMT_EPUB3 : "epub3",
GuiExportPandoc.FMT_ZIM : "zimwiki",
}
try:
import pypandoc
except:
self.theParent.makeAlert((
"Could not load the 'pypandoc' package. "
"Make sure it is installed, and try again."
), nwAlert.ERROR)
return False
inFile = self.tabMain.exportPath.text()
outFile = path.splitext(inFile)[0]+GuiExportPandoc.FMT_EXT[outFmt]
fileName = path.basename(outFile)
if path.isfile(outFile) and self.mainConf.showGUI:
msgBox = QMessageBox()
msgRes = msgBox.question(
self.theParent, "Overwrite",
("File '%s' already exists.<br>Do you want to overwrite it?" % fileName)
)
if msgRes != QMessageBox.Yes:
return False
try:
pypandoc.convert_file(
source_file = inFile,
format = inFmt,
outputfile = outFile,
to = pFmt[outFmt],
extra_args = (),
encoding = "utf-8",
filters = None
)
except Exception as e:
self.theParent.makeAlert(
["Failed to convert file using pypandoc + Pandoc.",
str(e)], nwAlert.ERROR
)
return False
return True
def _doClose(self): def _doClose(self):
logger.verbose("GuiExport close button clicked") logger.verbose("GuiExport close button clicked")
# General Settings
wNovel = self.tabMain.expNovel.isChecked() wNovel = self.tabMain.expNovel.isChecked()
wNotes = self.tabMain.expNotes.isChecked() wNotes = self.tabMain.expNotes.isChecked()
eFormat = self.tabMain.outputFormat.currentData() eFormat = self.tabMain.outputFormat.currentData()
fixWidth = self.tabMain.fixedWidth.value() fixWidth = self.tabMain.fixedWidth.value()
wComments = self.tabMain.expComments.isChecked() wComments = self.tabMain.expComments.isChecked()
wKeywords = self.tabMain.expKeywords.isChecked()
chFormat = self.tabMain.chapterFormat.text() chFormat = self.tabMain.chapterFormat.text()
unFormat = self.tabMain.unnumFormat.text() unFormat = self.tabMain.unnumFormat.text()
scFormat = self.tabMain.sceneFormat.text() scFormat = self.tabMain.sceneFormat.text()
seFormat = self.tabMain.sectionFormat.text() seFormat = self.tabMain.sectionFormat.text()
saveTo = self.tabMain.exportPath.text() saveTo = self.tabMain.exportPath.text()
hScene = self.tabMain.hideScene.isChecked()
hSection = self.tabMain.hideSection.isChecked()
self.optState.setSetting("wNovel", wNovel) self.optState.setSetting("wNovel", wNovel)
self.optState.setSetting("wNotes", wNotes) self.optState.setSetting("wNotes", wNotes)
self.optState.setSetting("eFormat", eFormat) self.optState.setSetting("eFormat", eFormat)
self.optState.setSetting("fixWidth", fixWidth) self.optState.setSetting("fixWidth", fixWidth)
self.optState.setSetting("wComments",wComments) self.optState.setSetting("wComments",wComments)
self.optState.setSetting("wKeywords",wKeywords)
self.optState.setSetting("chFormat", chFormat) self.optState.setSetting("chFormat", chFormat)
self.optState.setSetting("unFormat", unFormat) self.optState.setSetting("unFormat", unFormat)
self.optState.setSetting("scFormat", scFormat) self.optState.setSetting("scFormat", scFormat)
self.optState.setSetting("seFormat", seFormat) self.optState.setSetting("seFormat", seFormat)
self.optState.setSetting("saveTo", saveTo) self.optState.setSetting("saveTo", saveTo)
self.optState.setSetting("hScene", hScene)
self.optState.setSetting("hSection", hSection)
# Pandoc Settings
pFormat = self.tabPandoc.outputFormat.currentData()
self.optState.setSetting("pFormat", pFormat)
self.optState.saveSettings() self.optState.saveSettings()
self.close() self.close()
@@ -217,51 +311,44 @@ class GuiExport(QDialog):
class GuiExportMain(QWidget): class GuiExportMain(QWidget):
FMT_NWD = 1 # novelWriter markdown FMT_NWD = 1 # novelWriter markdown
FMT_TXT = 2 # Plain text file FMT_TXT = 2 # Plain text file
FMT_MD = 3 # Markdown file FMT_MD = 3 # Markdown file
FMT_HTML = 4 # HTML file FMT_HTML = 4 # HTML file
FMT_EBOOK = 5 # E-book friendly HTML FMT_TEX = 5 # LaTeX file
FMT_ODT = 6 # Open document FMT_PDOC = 6 # Pass to pandoc
FMT_TEX = 7 # LaTeX file FMT_EXT = {
FMT_EXT = { FMT_NWD : ".nwd",
FMT_NWD : ".nwd", FMT_TXT : ".txt",
FMT_TXT : ".txt", FMT_MD : ".md",
FMT_MD : ".md", FMT_HTML : ".htm",
FMT_HTML : ".htm", FMT_TEX : ".tex",
FMT_EBOOK : ".htm", FMT_PDOC : ".tmp",
FMT_ODT : ".odt",
FMT_TEX : ".tex",
} }
FMT_HELP = { FMT_HELP = {
FMT_NWD : ( FMT_NWD : (
"Exports a document using the novelWriter markdown format. " "Exports a document using the novelWriter markdown format. The files selected by the "
"The files selected by the filters are appended as-is, including comments and other settings." "filters are appended as-is, including comments and other settings."
), ),
FMT_TXT : ( FMT_TXT : (
"Exports a plain text file. " "Exports a plain text file. All formatting is stripped and comments are in square "
"All formatting is stripped and comments are in square brackets." "brackets."
), ),
FMT_MD : ( FMT_MD : (
"Exports a standard markdown file. " "Exports a standard markdown file. Comments are converted to preformatted text blocks."
"Comments are converted to preformatted text blocks."
), ),
FMT_HTML : ( FMT_HTML : (
"Exports a plain html5 file. " "Exports a plain html5 file. Comments are wrapped in blocks with a yellow background "
"Comments are wrapped in blocks with a yellow background colour." "colour."
),
FMT_EBOOK : (
"Exports an html5 file that can be converted to eBook with Calibre. "
"Comments are not exported in this format."
),
FMT_ODT : (
"Exports an open document file that can be read by office applications. "
"Comments are exported as grey text."
), ),
FMT_TEX : ( FMT_TEX : (
"Exports a LaTeX file that can be compiled to PDF using for instance PDFLaTeX. " "Exports a LaTeX file that can be compiled to PDF using for instance PDFLaTeX. "
"Comments are exported as LaTeX comments." "Comments are exported as LaTeX comments."
), ),
FMT_PDOC : (
"Exports first to markdown or html5. The file is then passed on to Pandoc for a second "
"stage. Use the Pandoc tab for settings up the conversion."
),
} }
def __init__(self, theParent, theProject, optState): def __init__(self, theParent, theProject, optState):
@@ -279,24 +366,27 @@ class GuiExportMain(QWidget):
self.guiFilesForm = QGridLayout(self) self.guiFilesForm = QGridLayout(self)
self.guiFiles.setLayout(self.guiFilesForm) self.guiFiles.setLayout(self.guiFilesForm)
self.expNovel = QCheckBox(self) self.expNovel = QCheckBox("Novel files",self)
self.expNovel.setChecked(self.optState.getSetting("wNovel")) self.expNovel.setChecked(self.optState.getSetting("wNovel"))
self.expNovel.setToolTip("Include all novel files in the exported document") self.expNovel.setToolTip("Include all novel files in the exported document")
self.expNotes = QCheckBox(self) self.expNotes = QCheckBox("Note files",self)
self.expNotes.setChecked(self.optState.getSetting("wNotes")) self.expNotes.setChecked(self.optState.getSetting("wNotes"))
self.expNotes.setToolTip("Include all note files in the exported document") self.expNotes.setToolTip("Include all note files in the exported document")
self.expComments = QCheckBox(self) self.expComments = QCheckBox("Comments",self)
self.expComments.setChecked(self.optState.getSetting("wComments")) self.expComments.setChecked(self.optState.getSetting("wComments"))
self.expComments.setToolTip("Export comments from all files") self.expComments.setToolTip("Export comments from all files")
self.guiFilesForm.addWidget(QLabel("Novel files"), 0, 0) self.expKeywords = QCheckBox("Keywords",self)
self.guiFilesForm.addWidget(self.expNovel, 0, 1) self.expKeywords.setChecked(self.optState.getSetting("wKeywords"))
self.guiFilesForm.addWidget(QLabel("Note files"), 1, 0) self.expKeywords.setToolTip("Export @keywords from all files")
self.guiFilesForm.addWidget(self.expNotes, 1, 1)
self.guiFilesForm.addWidget(QLabel("Comments"), 2, 0) self.guiFilesForm.addWidget(self.expNovel, 0, 1)
self.guiFilesForm.addWidget(self.expComments, 2, 1) self.guiFilesForm.addWidget(self.expComments, 0, 2)
self.guiFilesForm.addWidget(self.expNotes, 1, 1)
self.guiFilesForm.addWidget(self.expKeywords, 1, 2)
self.guiFilesForm.setRowStretch(2, 1)
# Chapter Settings # Chapter Settings
self.guiChapters = QGroupBox("Chapter Headings", self) self.guiChapters = QGroupBox("Chapter Headings", self)
@@ -333,10 +423,20 @@ class GuiExportMain(QWidget):
self.sectionFormat.setToolTip("Available formats: %title%") self.sectionFormat.setToolTip("Available formats: %title%")
self.sectionFormat.setMinimumWidth(100) self.sectionFormat.setMinimumWidth(100)
self.hideScene = QCheckBox("Skip",self)
self.hideScene.setChecked(self.optState.getSetting("hScene"))
self.hideScene.setToolTip("Skip scene titles in export")
self.hideSection = QCheckBox("Skip",self)
self.hideSection.setChecked(self.optState.getSetting("hSection"))
self.hideSection.setToolTip("Skip section titles in export")
self.guiScenesForm.addWidget(QLabel("Scenes"), 0, 0) self.guiScenesForm.addWidget(QLabel("Scenes"), 0, 0)
self.guiScenesForm.addWidget(self.sceneFormat, 0, 1) self.guiScenesForm.addWidget(self.sceneFormat, 0, 1)
self.guiScenesForm.addWidget(self.hideScene, 0, 2)
self.guiScenesForm.addWidget(QLabel("Sections"), 1, 0) self.guiScenesForm.addWidget(QLabel("Sections"), 1, 0)
self.guiScenesForm.addWidget(self.sectionFormat, 1, 1) self.guiScenesForm.addWidget(self.sectionFormat, 1, 1)
self.guiScenesForm.addWidget(self.hideSection, 1, 2)
# Output Path # Output Path
self.exportTo = QGroupBox("Export Folder", self) self.exportTo = QGroupBox("Export Folder", self)
@@ -367,13 +467,15 @@ class GuiExportMain(QWidget):
self.outputFormat.addItem("Plain Text (.txt)", self.FMT_TXT) self.outputFormat.addItem("Plain Text (.txt)", self.FMT_TXT)
self.outputFormat.addItem("Markdown (.md)", self.FMT_MD) self.outputFormat.addItem("Markdown (.md)", self.FMT_MD)
self.outputFormat.addItem("HTML5 (.htm)", self.FMT_HTML) self.outputFormat.addItem("HTML5 (.htm)", self.FMT_HTML)
# self.outputFormat.addItem("HTML5 for eBook (.htm)", self.FMT_EBOOK)
# self.outputFormat.addItem("Open Document (.odt)", self.FMT_ODT)
self.outputFormat.addItem("LaTeX for PDF (.tex)", self.FMT_TEX) self.outputFormat.addItem("LaTeX for PDF (.tex)", self.FMT_TEX)
self.outputFormat.addItem("Pandoc via Markdown or HTML", self.FMT_PDOC)
self.outputFormat.currentIndexChanged.connect(self._updateFormat) self.outputFormat.currentIndexChanged.connect(self._updateFormat)
optIdx = self.outputFormat.findData(self.optState.getSetting("eFormat")) optIdx = self.outputFormat.findData(self.optState.getSetting("eFormat"))
if optIdx != -1: if optIdx == -1:
self.outputFormat.setCurrentIndex(1)
self._updateFormat(1)
else:
self.outputFormat.setCurrentIndex(optIdx) self.outputFormat.setCurrentIndex(optIdx)
self._updateFormat(optIdx) self._updateFormat(optIdx)
@@ -383,7 +485,7 @@ class GuiExportMain(QWidget):
self.guiOutputForm.setColumnStretch(2, 1) self.guiOutputForm.setColumnStretch(2, 1)
# Additional Settings # Additional Settings
self.addSettings = QGroupBox("Additional Settings", self) self.addSettings = QGroupBox("Additional Settings (Format Dependent)", self)
self.addSettingsForm = QGridLayout(self) self.addSettingsForm = QGridLayout(self)
self.addSettings.setLayout(self.addSettingsForm) self.addSettings.setLayout(self.addSettingsForm)
@@ -438,13 +540,11 @@ class GuiExportMain(QWidget):
"Text files (*.txt)", "Text files (*.txt)",
"Markdown files (*.md)", "Markdown files (*.md)",
"HTML files (*.htm *.html)", "HTML files (*.htm *.html)",
# "Open document files (*.odt)",
"LaTeX files (*.tex)", "LaTeX files (*.tex)",
"All files (*.*)", "All files (*.*)",
] ]
dlgOpt = QFileDialog.Options() dlgOpt = QFileDialog.Options()
dlgOpt |= QFileDialog.ShowDirsOnly
dlgOpt |= QFileDialog.DontUseNativeDialog dlgOpt |= QFileDialog.DontUseNativeDialog
saveTo = QFileDialog.getSaveFileName( saveTo = QFileDialog.getSaveFileName(
self,"Export File",self.exportPath.text(),options=dlgOpt,filter=";;".join(extFilter) self,"Export File",self.exportPath.text(),options=dlgOpt,filter=";;".join(extFilter)
@@ -459,13 +559,109 @@ class GuiExportMain(QWidget):
def _checkFileExtension(self): def _checkFileExtension(self):
saveTo = self.exportPath.text() saveTo = self.exportPath.text()
fileBits = path.splitext(saveTo) fileBits = path.splitext(saveTo)
if self.currFormat > 0: if self.currFormat > 0 and fileBits[0].strip() != "":
saveTo = fileBits[0]+self.FMT_EXT[self.currFormat] saveTo = fileBits[0]+self.FMT_EXT[self.currFormat]
self.exportPath.setText(saveTo) self.exportPath.setText(saveTo)
return return
# END Class GuiExportMain # END Class GuiExportMain
class GuiExportPandoc(QWidget):
FMT_ODT = 1
FMT_DOCX = 2
FMT_EPUB2 = 4
FMT_EPUB3 = 5
FMT_ZIM = 6
FMT_EXT = {
FMT_ODT : ".odt",
FMT_DOCX : ".docx",
FMT_EPUB2 : ".epub",
FMT_EPUB3 : ".epub",
FMT_ZIM : ".txt",
}
FMT_VIA = {
FMT_ODT : "html",
FMT_DOCX : "html",
FMT_EPUB2 : "markdown",
FMT_EPUB3 : "markdown",
FMT_ZIM : "markdown",
}
def __init__(self, theParent, theProject, optState):
QWidget.__init__(self, theParent)
self.theParent = theParent
self.theProject = theProject
self.outerBox = QGridLayout()
self.optState = optState
try:
import pypandoc
self.hasPyPan = True
except:
self.hasPyPan = False
# Information
self.guiInfo = QGroupBox("Information", self)
self.guiInfoBox = QVBoxLayout(self)
self.guiInfo.setLayout(self.guiInfoBox)
self.infoHelp = QLabel("")
self.infoHelp.setWordWrap(True)
self.infoHelp.setMinimumHeight(55)
self.infoHelp.setAlignment(Qt.AlignTop)
self.guiInfoBox.addWidget(self.infoHelp)
if self.hasPyPan:
self.infoHelp.setText((
"Additional export to other document formats than in the Settings tab is provided "
"by Pandoc. the project is first exported to Markdown or HTML, depending on final "
"format, and then processed by Pandoc into the desired format."
))
else:
self.infoHelp.setText((
"The Python package 'pypandoc' is not installed or isn't working. This package is "
"required for interfacing with Pandoc. Please install it before proceeding."
))
# Output Format
self.guiOutput = QGroupBox("Pandoc Format", self)
self.guiOutputForm = QGridLayout(self)
self.guiOutput.setLayout(self.guiOutputForm)
self.outputFormat = QComboBox(self)
self.outputFormat.addItem("Open Office Document (.odt)", self.FMT_ODT)
self.outputFormat.addItem("Word Document (.docx)", self.FMT_DOCX)
self.outputFormat.addItem("ePUB eBook v2 (.epub2)", self.FMT_EPUB2)
self.outputFormat.addItem("ePUB eBook v3 (.epub3)", self.FMT_EPUB3)
self.outputFormat.addItem("Zim Wiki (.txt)", self.FMT_ZIM)
# self.outputFormat.currentIndexChanged.connect(self._updateFormat)
optIdx = self.outputFormat.findData(self.optState.getSetting("pFormat"))
if optIdx == -1:
self.outputFormat.setCurrentIndex(1)
else:
self.outputFormat.setCurrentIndex(optIdx)
self.guiOutputForm.addWidget(QLabel("Format"), 0, 0)
self.guiOutputForm.addWidget(self.outputFormat, 0, 1)
self.guiOutputForm.setColumnStretch(2, 1)
# Assemble
self.outerBox.addWidget(self.guiInfo, 0, 0)
self.outerBox.addWidget(self.guiOutput, 1, 0)
self.outerBox.setRowStretch(2, 1)
# self.outerBox.setColumnStretch(0, 1)
# self.outerBox.setColumnStretch(1, 1)
# self.outerBox.setColumnStretch(2, 1)
self.setLayout(self.outerBox)
return
# END Class GuiExportPandoc
class ExportLastState(OptLastState): class ExportLastState(OptLastState):
def __init__(self, theProject, theFile): def __init__(self, theProject, theFile):
@@ -474,17 +670,21 @@ class ExportLastState(OptLastState):
"wNovel" : True, "wNovel" : True,
"wNotes" : False, "wNotes" : False,
"eFormat" : 1, "eFormat" : 1,
"pFormat" : 1,
"fixWidth" : 80, "fixWidth" : 80,
"wComments" : False, "wComments" : False,
"wKeywords" : False,
"chFormat" : "Chapter %numword%", "chFormat" : "Chapter %numword%",
"unFormat" : "%title%", "unFormat" : "%title%",
"scFormat" : "* * *", "scFormat" : "* * *",
"seFormat" : "", "seFormat" : "",
"saveTo" : "", "saveTo" : "",
"hScene" : False,
"hSection" : False,
} }
self.stringOpt = ("chFormat","unFormat","scFormat","seFormat","saveTo") self.stringOpt = ("chFormat","unFormat","scFormat","seFormat","saveTo")
self.boolOpt = ("wNovel","wNotes","wComments") self.boolOpt = ("wNovel","wNotes","wComments","wKeywords","hScene","hSection")
self.intOpt = ("eFormat","fixWidth") self.intOpt = ("eFormat","pFormat","fixWidth")
return return
# END Class ExportLastState # END Class ExportLastState