Merge branch 'master' into large_text_performance
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
[](https://codecov.io/gh/vkbo/novelWriter)
|
||||
[](https://novelwriter.readthedocs.io/en/latest/?badge=latest)
|
||||
|
||||
novelWriter is a markdown-like text editor designed fro writing novels and larger projects of many smaller plain text documents.
|
||||
novelWriter is a markdown-like text editor designed for writing novels and larger projects of many smaller plain text documents.
|
||||
|
||||
The documentation is available here: [novelwriter.readthedocs.io](https://novelwriter.readthedocs.io/).
|
||||
|
||||
@@ -20,6 +20,34 @@ If you do use it for real projects, please run backups frequently to avoid data
|
||||
There is a built in backup feature that can pack the entire project into a zip file on close.
|
||||
Please check the documentation for further details.
|
||||
|
||||
## Markdown Flavour
|
||||
|
||||
novelWriter is **not** a full-feature Markdown editor.
|
||||
It allows for a minimal set of formatting needed for writing text documents for novels.
|
||||
These are currently limited to:
|
||||
|
||||
* Headings level 1 to 4 using the `#` syntax only.
|
||||
* Bold, italic and underline text.
|
||||
* Hard line breaks using two or more spaces at the end of a line.
|
||||
|
||||
That is it.
|
||||
Features not supported in the editor are also not exported when using the export tool.
|
||||
|
||||
In addition, novelWriter adds the following, which is otherwise not supported by Markdown:
|
||||
|
||||
* A line starting with `%` is treated as a comment and not rendered on exports unless requested.
|
||||
Comments do not count towards the word count.
|
||||
* A set of meta data keyword/value sets starting with the character `@`.
|
||||
This is used for tagging and inter-linking documents.
|
||||
* Non-breaking spaces are supported as long as your system is using at least Qt 5.9.
|
||||
For earlier version, non-breaking spaces are converted to normal spaces when saving the document.
|
||||
This is done by the Qt library.
|
||||
* Tabs may be rendered, depending on export format.
|
||||
|
||||
The core export format that should render properly all supported features is the HTML export.
|
||||
This format also forms the basis of conversion to Office type document formats with Pandoc.
|
||||
Note that Pandoc itself strips some formatting from the document during conversion, so the final result may be different than expected.
|
||||
|
||||
## Implementation
|
||||
|
||||
The application is written in Python3 using Qt5 via PyQt5.
|
||||
|
||||
@@ -85,7 +85,8 @@ class ToMarkdown(Tokenizer):
|
||||
# indicating a new paragraph.
|
||||
if tType == self.T_EMPTY:
|
||||
if len(thisPar) > 0:
|
||||
self.theResult += "%s\n\n" % " ".join(thisPar)
|
||||
tTemp = "\n".join(thisPar)
|
||||
self.theResult += "%s\n\n" % tTemp.rstrip()
|
||||
thisPar = []
|
||||
|
||||
elif tType == self.T_HEAD1:
|
||||
@@ -104,7 +105,7 @@ class ToMarkdown(Tokenizer):
|
||||
self.theResult += "%s\n\n" % tText
|
||||
|
||||
elif tType == self.T_SKIP:
|
||||
self.theResult += "\n\n\n\n"
|
||||
self.theResult += "\n\n\n"
|
||||
|
||||
elif tType == self.T_TEXT:
|
||||
thisPar.append(tText)
|
||||
|
||||
@@ -122,8 +122,8 @@ class ToText(Tokenizer):
|
||||
tText = self._centreText(tText,self.wordWrap)
|
||||
self.theResult += "%s\n\n" % tText
|
||||
|
||||
elif tType == self.T_SEP:
|
||||
self.theResult += "\n\n\n\n"
|
||||
elif tType == self.T_SKIP:
|
||||
self.theResult += "\n\n\n"
|
||||
|
||||
elif tType == self.T_TEXT:
|
||||
thisPar.append(tText)
|
||||
|
||||
@@ -44,7 +44,6 @@ class GuiConfigEditor(QDialog):
|
||||
self.setWindowTitle("Preferences")
|
||||
self.guiDeco = self.theParent.theTheme.loadDecoration("settings",(64,64))
|
||||
|
||||
self.theProject.countStatus()
|
||||
self.tabMain = GuiConfigEditGeneral(self.theParent)
|
||||
self.tabEditor = GuiConfigEditEditor(self.theParent)
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ class GuiExport(QDialog):
|
||||
|
||||
self.guiDeco = self.theParent.theTheme.loadDecoration("export",(64,64))
|
||||
|
||||
self.theProject.countStatus()
|
||||
self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState)
|
||||
self.tabPandoc = GuiExportPandoc(self.theParent, self.theProject, self.optState)
|
||||
|
||||
|
||||
@@ -229,6 +229,14 @@ class GuiDocEditor(QTextEdit):
|
||||
|
||||
return True
|
||||
|
||||
def replaceText(self, theText):
|
||||
"""Replaces the text of the current document with the provided
|
||||
text. This also clears undo history.
|
||||
"""
|
||||
self.setPlainText(theText)
|
||||
self.setDocumentChanged(True)
|
||||
return
|
||||
|
||||
def saveText(self):
|
||||
|
||||
if self.nwDocument.theItem is None:
|
||||
|
||||
+6
-3
@@ -417,17 +417,20 @@ class GuiMain(QMainWindow):
|
||||
)
|
||||
if inPath:
|
||||
loadFile = inPath[0]
|
||||
self.mainConf.setLastPath(loadFile)
|
||||
else:
|
||||
return False
|
||||
|
||||
if loadFile.strip() == "":
|
||||
return False
|
||||
|
||||
theText = None
|
||||
try:
|
||||
with open(loadFile,mode="rt",encoding="utf8") as inFile:
|
||||
theText = inFile.read()
|
||||
self.mainConf.setLastPath(loadFile)
|
||||
except Exception as e:
|
||||
self.makeAlert(
|
||||
["Could not read file. The file cannot be a binary file.",str(e)],
|
||||
["Could not read file. The file must be an existing text file.",str(e)],
|
||||
nwAlert.ERROR
|
||||
)
|
||||
return False
|
||||
@@ -451,7 +454,7 @@ class GuiMain(QMainWindow):
|
||||
else:
|
||||
return False
|
||||
|
||||
self.docEditor.setText(theText)
|
||||
self.docEditor.replaceText(theText)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -582,6 +582,9 @@ class NWProject():
|
||||
return True
|
||||
|
||||
def countStatus(self):
|
||||
"""Count how many times the various status flags are used in the
|
||||
project tree.
|
||||
"""
|
||||
self.statusItems.resetCounts()
|
||||
self.importItems.resetCounts()
|
||||
for nwItem in self.projTree.values():
|
||||
|
||||
@@ -41,6 +41,8 @@ class NWStatus():
|
||||
return True
|
||||
|
||||
def lookupEntry(self, theLabel):
|
||||
if theLabel is None:
|
||||
return None
|
||||
theLabel = theLabel.strip()
|
||||
if theLabel in self.theMap.keys():
|
||||
return self.theMap[theLabel]
|
||||
|
||||
Reference in New Issue
Block a user