Documentation and ODT exporter updates (#859)
* Clean up a few things in the ODT exporter * Remove local HTML docs and instead add PDF docs * Update documentation
This commit is contained in:
committed by
GitHub
parent
eee0f5e4c9
commit
95c79e1c23
@@ -18,6 +18,8 @@ i18n/*.qph
|
||||
# Documentation
|
||||
/docs/build/
|
||||
/nw/assets/help/html/
|
||||
/nw/assets/help/manual.pdf
|
||||
/UserManual.pdf
|
||||
*.qch
|
||||
*.qhc
|
||||
|
||||
|
||||
+19
-40
@@ -4,20 +4,15 @@
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath("."))
|
||||
|
||||
# -- Imports -----------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import time
|
||||
import sphinx_rtd_theme # noqa: F401
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# -- Project Information -----------------------------------------------------
|
||||
|
||||
project = "novelWriter"
|
||||
copyright = "2018–2021, Veronica Berglyd Olsen"
|
||||
@@ -28,7 +23,7 @@ version = "1.5"
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = "1.5-alpha0"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# -- General Configuration ---------------------------------------------------
|
||||
|
||||
os.environ["TZ"] = "Europe/Oslo"
|
||||
time.tzset()
|
||||
@@ -45,7 +40,7 @@ language = None
|
||||
exclude_patterns = []
|
||||
pygments_style = None
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# -- Options for HTML Output -------------------------------------------------
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_logo = "images/novelwriter.png"
|
||||
@@ -64,48 +59,32 @@ html_css_files = [
|
||||
"css/custom.css",
|
||||
]
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
# The default sidebars (for documents that don"t match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``["localtoc.html", "relations.html", "sourcelink.html",
|
||||
# "searchbox.html"]``.
|
||||
# html_sidebars = {}
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
# -- Options for HTMLHelp Output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "novelWriterDoc"
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
# -- Options for LaTeX Output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ("letterpaper" or "a4paper").
|
||||
#
|
||||
# "papersize": "letterpaper",
|
||||
|
||||
# The font size ("10pt", "11pt" or "12pt").
|
||||
#
|
||||
# "pointsize": "10pt",
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# "preamble": "",
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# "figure_align": "htbp",
|
||||
"papersize": "a4paper",
|
||||
"pointsize": "11pt",
|
||||
"preamble": (
|
||||
"\\usepackage[utf8]{inputenc}\n"
|
||||
"\\DeclareUnicodeCharacter{2212}{\\textendash}\n"
|
||||
),
|
||||
"figure_align": "htbp",
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [(
|
||||
master_doc, "novelWriter.tex", "novelWriter Documentation",
|
||||
master_doc, "manual.tex", "novelWriter Documentation",
|
||||
author, "manual"
|
||||
)]
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
# -- Options for Man Page Output ---------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
@@ -113,7 +92,7 @@ man_pages = [(
|
||||
master_doc, "novelwriter", "novelWriter Documentation", [author], 1
|
||||
)]
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
# -- Options for Texinfo Output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
@@ -123,7 +102,7 @@ texinfo_documents = [(
|
||||
"novelWriter", "Markdown-like editor for novels.", "Miscellaneous"
|
||||
)]
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
# -- Options for EPub Output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
@@ -2,27 +2,29 @@
|
||||
novelWriter |release|
|
||||
#####################
|
||||
|
||||
.. image:: https://github.com/vkbo/novelWriter/workflows/python%203.8/badge.svg?branch=main
|
||||
.. only:: html
|
||||
|
||||
.. image:: https://github.com/vkbo/novelWriter/workflows/python%203.8/badge.svg?branch=main
|
||||
:target: https://github.com/vkbo/novelWriter/actions
|
||||
:alt: Python Tests
|
||||
|
||||
.. image:: https://codecov.io/gh/vkbo/novelWriter/branch/main/graph/badge.svg
|
||||
.. image:: https://codecov.io/gh/vkbo/novelWriter/branch/main/graph/badge.svg
|
||||
:target: https://codecov.io/gh/vkbo/novelWriter
|
||||
:alt: Code Coverage
|
||||
|
||||
.. image:: https://readthedocs.org/projects/novelwriter/badge/?version=latest
|
||||
.. image:: https://readthedocs.org/projects/novelwriter/badge/?version=latest
|
||||
:target: https://novelwriter.readthedocs.io/en/latest/?badge=latest
|
||||
:alt: Documentation
|
||||
|
||||
.. image:: https://img.shields.io/github/v/release/vkbo/novelwriter
|
||||
.. image:: https://img.shields.io/github/v/release/vkbo/novelwriter
|
||||
:target: https://github.com/vkbo/novelWriter/releases
|
||||
:alt: GitHub Release
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/novelwriter
|
||||
.. image:: https://img.shields.io/pypi/v/novelwriter
|
||||
:target: https://pypi.org/project/novelWriter/
|
||||
:alt: PyPI
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/novelwriter
|
||||
.. image:: https://img.shields.io/pypi/pyversions/novelwriter
|
||||
:target: https://pypi.org/project/novelWriter/
|
||||
:alt: Python Version
|
||||
|
||||
@@ -101,6 +103,7 @@ for your operating system for further details.
|
||||
:caption: Under the Hood
|
||||
|
||||
tech_storage
|
||||
tech_tests
|
||||
|
||||
|
||||
Indices and Tables
|
||||
|
||||
@@ -157,13 +157,15 @@ The documentation can then be built from the ``docs`` folder in the source code
|
||||
If successful, the documentation should be available in the ``docs/build/html`` folder and you can
|
||||
open the ``index.html`` file in your browser.
|
||||
|
||||
You can also build the documentation by using the setup script:
|
||||
You can also build the PDF documentation locally using the setup script:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python setup.py docs
|
||||
python setup.py pdfdocs
|
||||
|
||||
This does the same as the ``make help`` command, but in addition it copies the documentation into
|
||||
novelWriter's assets folder. This will make it possible to open the documentation from inside of
|
||||
novelWriter by pressing :kbd:`F1` even without an internet connection, as it will instead open the
|
||||
local copy.
|
||||
This will build the documentation as a PDF using LaTeX. The file will then be copied into the
|
||||
assets folder and made available in the :guilabel:`Help` menu in novelWriter. The Sphinx build
|
||||
system has a few extra dependencies when building the PDF. Please check the `Sphinx Docs`_ if you
|
||||
have any issues.
|
||||
|
||||
.. _Sphinx Docs: https://www.sphinx-doc.org/
|
||||
|
||||
@@ -35,9 +35,9 @@ your own backup solution.
|
||||
extensions `.json` as JSON files are used to cache the index and various run-time settings and
|
||||
are generally large files that change often. You'd also want to exclude the ``cache`` folder.
|
||||
|
||||
The project XML file is indent-formatted, suitable for diff tools and version control since most of
|
||||
the file will stay static, although a timesetamp is set in the meta section on line 2, and various
|
||||
meta data entries incremented, on each save.
|
||||
The project XML file is indent-formatted, and is suitable for diff tools and version control since
|
||||
most of the file will stay static, although a timesetamp is set in the meta section on line 2, and
|
||||
various meta data entries incremented, on each save.
|
||||
|
||||
|
||||
Project Documents
|
||||
@@ -45,7 +45,7 @@ Project Documents
|
||||
|
||||
All the project documents are saved in a folder in the main project folder named ``content``. Each
|
||||
document has a file handle taken from the first 13 characters of a SHA256 hash of the system time
|
||||
plus an incremented number when the document was first created. The documents are saved with a
|
||||
when the document was first created, plus an incremented number. The documents are saved with a
|
||||
filename assembled from this hash and the file extension ``.nwd``.
|
||||
|
||||
If you wish to find the file system location of a document in the project, you can either look it
|
||||
@@ -60,7 +60,7 @@ what the user names the document within the project, or changes it to.
|
||||
|
||||
Each document file contains a plain text version of the text from the editor. The file can in
|
||||
principle be edited in any text editor, and is suitable for diffing and version control if so
|
||||
desired. Just make sure the file remains in utf-8 encoding, otherwise unicode chatracters may
|
||||
desired. Just make sure the file remains in utf-8 encoding, otherwise unicode characters may
|
||||
become mangled when the file is opened in novelWriter again.
|
||||
|
||||
Editing these files is generally not recommended outside of special circumstances, whatever they
|
||||
@@ -115,7 +115,7 @@ project, and the word counts within each header section.
|
||||
|
||||
The integrity of the index is checked when the file is loaded. It is possible to corrupt the index
|
||||
if the file is manually edited and manipulated, so the check is important to avoid sudden crashes
|
||||
of novelWriter. if the file contains errors, novelWriter will automatically build it anew. If the
|
||||
of novelWriter. If the file contains errors, novelWriter will automatically build it anew. If the
|
||||
check somehow fails and novelWriter keeps crashing, you can delete the file manually and rebuild
|
||||
the index. If this too fails, you have likely encountered a bug.
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
.. _a_pytest:
|
||||
|
||||
*************
|
||||
Running Tests
|
||||
*************
|
||||
|
||||
The novelWriter source code is well covered by tests. The test framework used for the development
|
||||
is ``pytest`` with the use of an extension for Qt.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
The dependencies for running the tests can be installed with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
pip install -r requirements-dev.txt
|
||||
|
||||
This will install a couple of extra packages for coverage and test management. The minimum
|
||||
requirement is just ``pytest`` and ``pytest-qt``.
|
||||
|
||||
|
||||
Simple Test Run
|
||||
===============
|
||||
|
||||
To run the tests, you simply need to execute the following from the root of the source folder:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
pytest
|
||||
|
||||
Since several of the tests involve opening up the novelWriter GUI, you may want to disable the GUI
|
||||
for the duration of the test run. Moving your mouse while the tests are running may otherwise
|
||||
interfere with the execution of some tests.
|
||||
|
||||
You can disable the renderring of the GUI by setting the flag ``export QT_QPA_PLATFORM=offscreen``,
|
||||
or alternatively run the tests with the ``xvfb`` package, like so:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
xvfb-run pytest
|
||||
|
||||
|
||||
Advanced Options
|
||||
================
|
||||
|
||||
Adding the flag ``-v`` to the ``pytest`` command will increase verbosity of the test execution.
|
||||
|
||||
You can also add coverage report generation. For instance to HTML:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
xvfb-run pytest -v --cov=nw --cov-report=html
|
||||
|
||||
Other useful report formats are ``xml``, and ``term`` for terminal output.
|
||||
|
||||
You can also run tests per subpackage of novelWriter with the ``-m`` command. The available
|
||||
subpackage groups are ``base``, ``core``, and ``gui``. Consider for instance:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
xvfb-run pytest -v --cov=nw --cov-report=html -m core
|
||||
|
||||
This will only run the tests of the "core" package, that is, all the classes that deal with the
|
||||
project data of a novelWriter project. The "gui" tests, likewise, will run the tests for the GUI
|
||||
components, and the "base" tests cover the bits in-between.
|
||||
|
||||
You can also filter the tests with the ``-k`` switch. The following will do the same as
|
||||
``-m core``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
xvfb-run pytest -v --cov=nw --cov-report=html -k testCore
|
||||
|
||||
All tests are named in such a way that you can filter them by adding more bits of the test names.
|
||||
They all start with the word "test". Then comes the group: "Core", "Base", "Dlg", "Tool", or "Gui".
|
||||
Finally comes the name of the class or module, which generally corresponds to a single source code
|
||||
file. For instance, running the following will run all tests for the document editor:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
xvfb-run pytest -v --cov=nw --cov-report=html -k testGuiEditor
|
||||
|
||||
To run a single test, simply add the full test name to the ``-k`` switch.
|
||||
@@ -80,7 +80,7 @@ The main shorcuts are as follows:
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`W`", "Close the current project."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Z`", "Undo move of project tree item."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`Del`", "If in the project tree, move a document to trash, or delete a folder."
|
||||
":kbd:`F1`", "Open the documentation. This will either open the Qt Assistant, if available, or send you to the documentation website."
|
||||
":kbd:`F1`", "Open the online user manual."
|
||||
":kbd:`F2`", "If in the project tree, edit a document or folder settings. (Same as :kbd:`Ctrl`:kbd:`E`)"
|
||||
":kbd:`F3`", "Find next occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`G`)"
|
||||
":kbd:`F5`", "Open the :guilabel:`Build Novel Project` dialog."
|
||||
@@ -90,7 +90,7 @@ The main shorcuts are as follows:
|
||||
":kbd:`F9`", "Re-build the project index."
|
||||
":kbd:`F10`", "Re-build the project outline."
|
||||
":kbd:`F11`", "Activate full screen mode."
|
||||
":kbd:`Shift`:kbd:`F1`", "Open the online documentation in the system default browser."
|
||||
":kbd:`Shift`:kbd:`F1`", "Open the local user manual (PDF) if it is available."
|
||||
":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`Shift`:kbd:`G`.)"
|
||||
":kbd:`Shift`:kbd:`F6`", "Open the :guilabel:`Project Details` dialog."
|
||||
":kbd:`Return`", "If in the project tree, open a document for editing."
|
||||
|
||||
@@ -71,6 +71,7 @@ class Config:
|
||||
self.themeRoot = None # The full path to the nw/assets/themes folder
|
||||
self.dictPath = None # The full path to the nw/assets/dict folder
|
||||
self.iconPath = None # The full path to the nw/assets/icons folder
|
||||
self.pdfDocs = None # The location of the PDF manual, if it exists
|
||||
|
||||
# Runtime Settings and Variables
|
||||
self.confChanged = False # True whenever the config has chenged, false after save
|
||||
@@ -356,6 +357,16 @@ class Config:
|
||||
if self.spellLanguage is None:
|
||||
self.spellLanguage = "en"
|
||||
|
||||
# Look for a PDF version of the manual
|
||||
lookIn = [
|
||||
os.path.join(self.assetPath, "help", "manual.pdf"),
|
||||
os.path.join(self.appRoot, "UserManual.pdf"),
|
||||
]
|
||||
for pdfDocs in lookIn:
|
||||
if os.path.isfile(pdfDocs):
|
||||
self.pdfDocs = pdfDocs
|
||||
break
|
||||
|
||||
logger.debug("Config initialisation complete")
|
||||
|
||||
return True
|
||||
|
||||
+22
-14
@@ -107,7 +107,7 @@ class ToOdt(Tokenizer):
|
||||
self.headerText = ""
|
||||
|
||||
# Internal
|
||||
self._fontFamily = "'Liberation Sans'"
|
||||
self._fontFamily = "'Liberation Serif'"
|
||||
self._fontPitch = "variable"
|
||||
self._fSizeTitle = "30pt"
|
||||
self._fSizeHead1 = "24pt"
|
||||
@@ -239,6 +239,9 @@ class ToOdt(Tokenizer):
|
||||
self._blockIndent = self._emToCm(self.blockIndent)
|
||||
self._textAlign = "justify" if self.doJustify else "left"
|
||||
|
||||
# Clear Errors
|
||||
self._errData = []
|
||||
|
||||
# Document Header
|
||||
# ===============
|
||||
|
||||
@@ -546,8 +549,8 @@ class ToOdt(Tokenizer):
|
||||
rFmt += "_B%s b_ " % (" "*len(tText))
|
||||
if len(theBits) > 1:
|
||||
if theBits[0] == nwKeyWords.TAG_KEY:
|
||||
rTxt += "%s" % theBits[1]
|
||||
rFmt += "%s" % (" "*len(theBits[1]))
|
||||
rTxt += theBits[1]
|
||||
rFmt += " "*len(theBits[1])
|
||||
else:
|
||||
tTags = ", ".join(theBits[1:])
|
||||
rTxt += tTags
|
||||
@@ -585,12 +588,15 @@ class ToOdt(Tokenizer):
|
||||
tTemp = ""
|
||||
xFmt = 0x00
|
||||
pFmt = 0x00
|
||||
pErr = 0
|
||||
|
||||
parProc = XMLParagraph(xElem)
|
||||
|
||||
for i, c in enumerate(theText):
|
||||
|
||||
if theFmt[i] == "_":
|
||||
if theFmt[i] == " ":
|
||||
tTemp += c
|
||||
elif theFmt[i] == "_":
|
||||
continue
|
||||
elif theFmt[i] == "B":
|
||||
xFmt |= X_BLD
|
||||
@@ -604,9 +610,8 @@ class ToOdt(Tokenizer):
|
||||
xFmt |= X_DEL
|
||||
elif theFmt[i] == "s":
|
||||
xFmt &= M_DEL
|
||||
|
||||
if theFmt[i] == " ":
|
||||
tTemp += c
|
||||
else:
|
||||
pErr += 1
|
||||
|
||||
if xFmt != pFmt:
|
||||
if pFmt == 0x00:
|
||||
@@ -624,6 +629,9 @@ class ToOdt(Tokenizer):
|
||||
else:
|
||||
parProc.appendSpan(tTemp, self._textStyle(pFmt))
|
||||
|
||||
if pErr > 0:
|
||||
self._errData.append("Unknown format tag encountered")
|
||||
|
||||
nErr, errMsg = parProc.checkError()
|
||||
if nErr > 0: # pragma: no cover
|
||||
# This one should only capture bugs
|
||||
@@ -652,23 +660,23 @@ class ToOdt(Tokenizer):
|
||||
|
||||
return newName
|
||||
|
||||
def _textStyle(self, styleCode):
|
||||
def _textStyle(self, tFmt):
|
||||
"""Return a text style for a given style code.
|
||||
"""
|
||||
if styleCode in self._autoText:
|
||||
return self._autoText[styleCode][0]
|
||||
if tFmt in self._autoText:
|
||||
return self._autoText[tFmt][0]
|
||||
|
||||
newName = "T%d" % (len(self._autoText) + 1)
|
||||
newStyle = ODTTextStyle()
|
||||
if styleCode & X_BLD:
|
||||
if tFmt & X_BLD:
|
||||
newStyle.setFontWeight("bold")
|
||||
if styleCode & X_ITA:
|
||||
if tFmt & X_ITA:
|
||||
newStyle.setFontStyle("italic")
|
||||
if styleCode & X_DEL:
|
||||
if tFmt & X_DEL:
|
||||
newStyle.setStrikeStyle("solid")
|
||||
newStyle.setStrikeType("single")
|
||||
|
||||
self._autoText[styleCode] = (newName, newStyle)
|
||||
self._autoText[tFmt] = (newName, newStyle)
|
||||
|
||||
return newName
|
||||
|
||||
|
||||
+17
-29
@@ -23,11 +23,9 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import nw
|
||||
import logging
|
||||
|
||||
from http.client import HTTPSConnection
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import pathname2url
|
||||
|
||||
@@ -137,31 +135,13 @@ class GuiMainMenu(QMenuBar):
|
||||
QDesktopServices.openUrl(QUrl(theUrl))
|
||||
return True
|
||||
|
||||
def _openDocumentation(self):
|
||||
"""Open the documentation, and select whether it should be the
|
||||
stable or latest version. If no internet connection, open
|
||||
local.
|
||||
def _openUserManualFile(self):
|
||||
"""Open the documentation in PDF format.
|
||||
"""
|
||||
if nw.__hexversion__[-2] == "f":
|
||||
docsPath = "/en/stable/"
|
||||
else:
|
||||
docsPath = "/en/latest/"
|
||||
|
||||
try:
|
||||
conn = HTTPSConnection(nw.__docurl__.replace("https://", ""))
|
||||
conn.request("HEAD", docsPath)
|
||||
resp = conn.getresponse()
|
||||
hasAccess = resp.code == 200
|
||||
except Exception:
|
||||
hasAccess = False
|
||||
|
||||
docsFile = os.path.join(self.mainConf.assetPath, "help", "html", "index.html")
|
||||
if hasAccess or not os.path.isfile(docsFile):
|
||||
self._openWebsite(nw.__docurl__ + docsPath)
|
||||
else:
|
||||
self._openWebsite(urljoin("file:", pathname2url(docsFile)))
|
||||
|
||||
return
|
||||
if self.mainConf.pdfDocs is None:
|
||||
return False
|
||||
QDesktopServices.openUrl(QUrl(urljoin("file:", pathname2url(self.mainConf.pdfDocs))))
|
||||
return True
|
||||
|
||||
##
|
||||
# Menu Builders
|
||||
@@ -1106,13 +1086,21 @@ class GuiMainMenu(QMenuBar):
|
||||
# Help > Separator
|
||||
self.helpMenu.addSeparator()
|
||||
|
||||
# Help > Documentation
|
||||
self.aHelpDocs = QAction(self.tr("Documentation"), self)
|
||||
# Help > User Manual (Online)
|
||||
self.aHelpDocs = QAction(self.tr("User Manual (Online)"), self)
|
||||
self.aHelpDocs.setStatusTip(self.tr("Open documentation in browser"))
|
||||
self.aHelpDocs.triggered.connect(self._openDocumentation)
|
||||
self.aHelpDocs.setShortcut("F1")
|
||||
self.aHelpDocs.triggered.connect(lambda: self._openWebsite(nw.__docurl__))
|
||||
self.helpMenu.addAction(self.aHelpDocs)
|
||||
|
||||
# Help > User Manual (PDF)
|
||||
if self.mainConf.pdfDocs is not None:
|
||||
self.aPdfDocs = QAction(self.tr("User Manual (PDF)"), self)
|
||||
self.aPdfDocs.setStatusTip(self.tr("Open PDF documentation"))
|
||||
self.aPdfDocs.setShortcut("Shift+F1")
|
||||
self.aPdfDocs.triggered.connect(self._openUserManualFile)
|
||||
self.helpMenu.addAction(self.aPdfDocs)
|
||||
|
||||
# Help > Separator
|
||||
self.helpMenu.addSeparator()
|
||||
|
||||
|
||||
@@ -1373,6 +1373,8 @@ class GuiMain(QMainWindow):
|
||||
|
||||
# Help
|
||||
self.addAction(self.mainMenu.aHelpDocs)
|
||||
if self.mainConf.pdfDocs is not None:
|
||||
self.addAction(self.mainMenu.aPdfDocs)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -222,35 +222,51 @@ def buildQtDocs():
|
||||
|
||||
|
||||
##
|
||||
# Html Documentation Builder (docs)
|
||||
# Html or PDF Documentation Builder (docs, docs_pdf)
|
||||
##
|
||||
|
||||
def buildHtmlDocs():
|
||||
"""This function will build the Sphinx HTML documentation. The files
|
||||
are then copied into the nw/assets/help/html directory and can be
|
||||
included in builds.
|
||||
def buildLocalDocs(bldFmt="HTML"):
|
||||
"""This function will build the Sphinx HTML or PDF documentation.
|
||||
For HTML, the files are then copied into the nw/assets/help/html
|
||||
directory and can be included in builds.
|
||||
"""
|
||||
buildDir = os.path.join("docs", "build", "html")
|
||||
helpDir = os.path.join("nw", "assets", "help", "html")
|
||||
|
||||
print("")
|
||||
print("Building Documentation")
|
||||
print("======================")
|
||||
print("Format: %s" % bldFmt)
|
||||
print("")
|
||||
|
||||
if bldFmt == "HTML":
|
||||
buildDir = os.path.join("docs", "build", "html")
|
||||
elif bldFmt == "PDF":
|
||||
buildDir = os.path.join("docs", "build", "latex")
|
||||
else:
|
||||
print("Docs Build Error:")
|
||||
return
|
||||
|
||||
buildFail = False
|
||||
try:
|
||||
subprocess.call(["make", "-C", "docs", "clean"])
|
||||
if bldFmt == "HTML":
|
||||
subprocess.call(["make", "-C", "docs", "html"])
|
||||
elif bldFmt == "PDF":
|
||||
subprocess.call(["make", "-C", "docs", "latexpdf"])
|
||||
except Exception as e:
|
||||
print("Docs Build Error:")
|
||||
print(str(e))
|
||||
buildFail = True
|
||||
|
||||
try:
|
||||
if bldFmt == "HTML":
|
||||
helpDir = os.path.join("nw", "assets", "help", "html")
|
||||
if os.path.isdir(helpDir):
|
||||
shutil.rmtree(helpDir)
|
||||
shutil.copytree(buildDir, helpDir)
|
||||
elif bldFmt == "PDF":
|
||||
os.rename(
|
||||
os.path.join(buildDir, "manual.pdf"),
|
||||
os.path.join("nw", "assets", "help", "manual.pdf")
|
||||
)
|
||||
except Exception as e:
|
||||
print("Docs Build Error:")
|
||||
print(str(e))
|
||||
@@ -262,7 +278,11 @@ def buildHtmlDocs():
|
||||
print("")
|
||||
print("Dependencies:")
|
||||
print(" * pip install sphinx")
|
||||
if bldFmt == "HTML":
|
||||
print(" * pip install sphinx-rtd-theme")
|
||||
elif bldFmt == "PDF":
|
||||
print(" * Package latexmk")
|
||||
print(" * LaTeX build system")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Documentation build: OK")
|
||||
@@ -401,7 +421,7 @@ def makeMinimalPackage(targetOS):
|
||||
|
||||
# Build docs
|
||||
try:
|
||||
buildHtmlDocs()
|
||||
buildLocalDocs(bldFmt="PDF")
|
||||
except Exception as e:
|
||||
print("Failed with error:")
|
||||
print(str(e))
|
||||
@@ -440,7 +460,19 @@ def makeMinimalPackage(targetOS):
|
||||
if os.path.isfile(outFile):
|
||||
os.unlink(outFile)
|
||||
|
||||
rootFiles = ["LICENSE.md", "README.md", "CHANGELOG.md", "requirements.txt", "setup.py"]
|
||||
# Add the manual also to the root
|
||||
pdfDocs = os.path.join("nw", "assets", "help", "manual.pdf")
|
||||
if os.path.isfile(pdfDocs):
|
||||
os.rename(pdfDocs, "UserManual.pdf")
|
||||
|
||||
rootFiles = [
|
||||
"CHANGELOG.md",
|
||||
"LICENSE.md",
|
||||
"README.md",
|
||||
"requirements.txt",
|
||||
"setup.py",
|
||||
"UserManual.pdf",
|
||||
]
|
||||
|
||||
with ZipFile(outFile, "w", compression=ZIP_DEFLATED, compresslevel=9) as zipObj:
|
||||
|
||||
@@ -1195,7 +1227,8 @@ if __name__ == "__main__":
|
||||
"",
|
||||
"Additional Builds:",
|
||||
"",
|
||||
" docs Build the help documentation as HTML."
|
||||
" htmldocs Build the help documentation as HTML.",
|
||||
" pdfdocs Build the help documentation as PDF (requires LaTeX).",
|
||||
" qthelp Build the help documentation for use with the Qt Assistant.",
|
||||
" qtlupdate Update the translation files for internationalisation.",
|
||||
" qtlrelease Build the language files for internationalisation.",
|
||||
@@ -1262,9 +1295,13 @@ if __name__ == "__main__":
|
||||
# Additional Builds
|
||||
# =================
|
||||
|
||||
if "docs" in sys.argv:
|
||||
sys.argv.remove("docs")
|
||||
buildHtmlDocs()
|
||||
if "htmldocs" in sys.argv:
|
||||
sys.argv.remove("htmldocs")
|
||||
buildLocalDocs(bldFmt="HTML")
|
||||
|
||||
if "pdfdocs" in sys.argv:
|
||||
sys.argv.remove("pdfdocs")
|
||||
buildLocalDocs(bldFmt="PDF")
|
||||
|
||||
if "qthelp" in sys.argv:
|
||||
sys.argv.remove("qthelp")
|
||||
|
||||
@@ -199,10 +199,10 @@ def testCoreToOdt_TextFormatting(mockGUI):
|
||||
|
||||
# Incorrectly Formatted Text
|
||||
theDoc.initDocument()
|
||||
theTxt = "A **few** _words"
|
||||
theFmt = " _b b_ I "
|
||||
theTxt = "A **few** _wordsXXX"
|
||||
theFmt = " _b b_ I XXX"
|
||||
theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt)
|
||||
assert theDoc.getErrors() == []
|
||||
assert theDoc.getErrors() == ["Unknown format tag encountered"]
|
||||
assert xmlToText(theDoc._xText) == (
|
||||
"<office:text>"
|
||||
"<text:p text:style-name=\"Standard\">"
|
||||
|
||||
Reference in New Issue
Block a user