+3
-1
@@ -1,7 +1,9 @@
|
||||
# Setup
|
||||
# Setup/Install
|
||||
MANIFEST
|
||||
dist/
|
||||
build/
|
||||
deploy/
|
||||
*.spec
|
||||
|
||||
# Documentation
|
||||
docs/build/
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
@@ -10,6 +10,7 @@ This is the documentation for novelWriter |version|.
|
||||
:maxdepth: 2
|
||||
|
||||
introduction
|
||||
started
|
||||
interface
|
||||
projects
|
||||
structure
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
***************
|
||||
Getting Started
|
||||
***************
|
||||
|
||||
You can download novelWriter from https://github.com/vkbo/novelWriter/releases
|
||||
|
||||
Latest version is |version|:
|
||||
|
||||
* ZIP file: https://github.com/vkbo/novelWriter/archive/v0.3.2.zip
|
||||
* TAR file: https://github.com/vkbo/novelWriter/archive/v0.3.2.tar.gz
|
||||
|
||||
Extract the archive to a location of your choice.
|
||||
|
||||
Installing Dependencies
|
||||
=======================
|
||||
|
||||
If you already have Python installed, and don't mind starting novelWriter from command line, all you need to do is to open your command line tool, find the folder and run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python -m pip install -r requirements.txt
|
||||
|
||||
On some operating systems you need to use ``python3`` instead of ``python``.
|
||||
|
||||
The following Python packages are required to run novelWriter:
|
||||
|
||||
* ``pyqt5`` for the GUI
|
||||
* ``appdirs`` for locating the system's config folder
|
||||
* ``lxml`` for writing project files
|
||||
|
||||
.. note::
|
||||
Sometimes the SVG graphics package for pyqt5 must be installed separately.
|
||||
|
||||
The following are optional, but recommended:
|
||||
|
||||
* ``pyenchant`` for spell checking
|
||||
* ``pycountry`` for translating language codes to language names
|
||||
* ``latexcodec`` for escaping unicode characters in LaTeX export
|
||||
* ``pypandoc`` for additional exports to Word, Open Office, eBooks, etc.
|
||||
|
||||
|
||||
Running novelWriter
|
||||
===================
|
||||
|
||||
If all the required dependencies are met, you can run novelWriter from the command line:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python novelWriter.py
|
||||
|
||||
A few switches are supported from the command line, mostly to assist in debugging if an error is encountered.
|
||||
To list all options, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python novelWriter.py --help
|
||||
|
||||
|
||||
Building a Standalone Executable
|
||||
================================
|
||||
|
||||
A standalone executable can be built with pyinstaller, using the python script named "install.py" in the source folder.
|
||||
This script will automatically try to install all dependencies and build the standalone executable of novelWriter.
|
||||
You can run the script by typing the following into your command prompt:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python install.py
|
||||
|
||||
If successful, the executable will be in the "dist" folder.
|
||||
|
||||
|
||||
Additional Instructions for Windows
|
||||
-----------------------------------
|
||||
|
||||
If you don't have Python installed, you can download it from the python.org website.
|
||||
The installers for Windows are available at https://www.python.org/downloads/windows/
|
||||
|
||||
novelWriter should work with Python 3.5 or higher, and the executable installer is the easiest to install.
|
||||
Please note that the `pyenchant` package for spell checking does not currently work with the x86-64 version, so if you want spell checking, you must install the x86 version.
|
||||
|
||||
Also, make sure you select the "Add Python to PATH" option.
|
||||
|
||||
.. image:: images/python_win_install.png
|
||||
:width: 600
|
||||
|
||||
Once Python is set up and running, you can either run novelWriter from the folder where you extracted it, or you can build an executable and run that from a desktop icon instead.
|
||||
|
||||
An install script is provided to automatically pull all dependencies and build a single executable.
|
||||
Open a command prompt in the folder where you extracted novelWriter, and run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python install.py
|
||||
|
||||
If everything went well, you should find a "novelWriter.exe" file in a folder named "dist".
|
||||
You can right-click it and create a desktop icon if you wish.
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
import subprocess
|
||||
|
||||
# Defaults
|
||||
buildWindowed = True
|
||||
|
||||
# Parse Options
|
||||
shortOpt = "hd"
|
||||
longOpt = [
|
||||
"help",
|
||||
"debug",
|
||||
]
|
||||
helpMsg = (
|
||||
"\n"
|
||||
"novelWriter Install Script\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
" -h, --help Print this message.\n"
|
||||
" -d, --debug Build novelWriter for debugging. To debug novelwriter after build,\n"
|
||||
" run it from command line with the debug options. Please check the\n"
|
||||
" novelWriter --help output for details.\n"
|
||||
)
|
||||
|
||||
try:
|
||||
inOpts, inArgs = getopt.getopt(sys.argv[1:],shortOpt,longOpt)
|
||||
except getopt.GetoptError:
|
||||
print(helpMsg)
|
||||
sys.exit(2)
|
||||
|
||||
for inOpt, inArg in inOpts:
|
||||
if inOpt in ("-h","--help"):
|
||||
print(helpMsg)
|
||||
sys.exit()
|
||||
elif inOpt in ("-d", "--debug"):
|
||||
buildWindowed = False
|
||||
|
||||
# Run pip
|
||||
packList = ["pyinstaller"]
|
||||
with open("requirements.txt",mode="r") as reqFile:
|
||||
for reqPack in reqFile:
|
||||
if len(reqPack.strip()) > 0:
|
||||
packList.append(reqPack)
|
||||
|
||||
for packName in packList:
|
||||
print("Installing package dependency: %s" % packName)
|
||||
try:
|
||||
subprocess.call([sys.executable, "-m", "pip", "install", packName])
|
||||
except Exception as e:
|
||||
print("Failed with error:")
|
||||
print(str(e))
|
||||
|
||||
# Run pyinstaller
|
||||
if sys.platform.startswith("win32"):
|
||||
dotDot = ";"
|
||||
else:
|
||||
dotDot = ":"
|
||||
|
||||
instOpt = [
|
||||
"--name=novelWriter",
|
||||
"--onefile",
|
||||
"--add-data=%s%s%s" % (os.path.join("nw", "themes"), dotDot,"themes"),
|
||||
"--add-data=%s%s%s" % (os.path.join("nw", "graphics"),dotDot,"graphics"),
|
||||
"--icon=%s" % os.path.join("nw", "graphics", "novelWriter.ico"),
|
||||
]
|
||||
if buildWindowed:
|
||||
instOpt.append("--windowed")
|
||||
|
||||
instOpt.append("novelWriter.py")
|
||||
|
||||
import PyInstaller.__main__
|
||||
PyInstaller.__main__.run(instOpt)
|
||||
|
||||
print("")
|
||||
print("##################")
|
||||
print(" Build Finished")
|
||||
print("##################")
|
||||
print("")
|
||||
print("If everything went well, the novelWriter executable should be in the folder named 'dist'")
|
||||
print("")
|
||||
|
||||
+7
-6
@@ -10,8 +10,9 @@
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import getopt
|
||||
import logging
|
||||
|
||||
from os import path, remove, rename
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
@@ -126,15 +127,15 @@ def main(sysArgs):
|
||||
inOpts, inArgs = getopt.getopt(sysArgs,shortOpt,longOpt)
|
||||
except getopt.GetoptError:
|
||||
print(helpMsg)
|
||||
exit(2)
|
||||
sys.exit(2)
|
||||
|
||||
for inOpt, inArg in inOpts:
|
||||
if inOpt in ("-h","--help"):
|
||||
if inOpt in ("-h","--help"):
|
||||
print(helpMsg)
|
||||
exit()
|
||||
sys.exit()
|
||||
elif inOpt in ("-v", "--version"):
|
||||
print("%s %s Version %s" % (__package__,__status__,__version__))
|
||||
exit()
|
||||
sys.exit()
|
||||
elif inOpt in ("-d", "--debug"):
|
||||
debugLevel = logging.DEBUG
|
||||
debugStr = "{name:>22}:{lineno:<4d} {levelname:8} {message:}"
|
||||
@@ -196,6 +197,6 @@ def main(sysArgs):
|
||||
else:
|
||||
nwApp = QApplication([__package__])
|
||||
nwGUI = GuiMain()
|
||||
exit(nwApp.exec_())
|
||||
sys.exit(nwApp.exec_())
|
||||
|
||||
return
|
||||
|
||||
+3
-3
@@ -158,13 +158,13 @@ class Config:
|
||||
self.confFile = self.appHandle+".conf"
|
||||
self.homePath = path.expanduser("~")
|
||||
self.lastPath = self.homePath
|
||||
self.appPath = path.dirname(__file__)
|
||||
self.appPath = getattr(sys, "_MEIPASS", path.abspath(path.dirname(__file__)))
|
||||
self.appRoot = path.join(self.appPath,path.pardir)
|
||||
self.helpPath = path.join(self.appRoot,"help","en_GB")
|
||||
self.guiPath = path.join(self.appPath,"gui")
|
||||
self.themeRoot = path.join(self.appPath,"themes")
|
||||
self.themePath = path.join(self.themeRoot)
|
||||
self.appIcon = path.join(self.appRoot, nwFiles.APP_ICON)
|
||||
self.graphPath = path.join(self.appPath,"graphics")
|
||||
self.appIcon = path.join(self.graphPath, nwFiles.APP_ICON)
|
||||
|
||||
# If config folder does not exist, make it.
|
||||
# This assumes that the os config folder itself exists.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -43,7 +43,7 @@ class GuiConfigEditor(QDialog):
|
||||
|
||||
self.setWindowTitle("Preferences")
|
||||
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","gear.svg"))
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
||||
self.svgGradient = QSvgWidget(path.join(self.gradPath))
|
||||
self.svgGradient.setFixedSize(QSize(64,64))
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class GuiExport(QDialog):
|
||||
self.setWindowTitle("Export Project")
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","export.svg"))
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"export.svg"))
|
||||
self.svgGradient = QSvgWidget(self.gradPath)
|
||||
self.svgGradient.setFixedSize(QSize(64,64))
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class GuiItemEditor(QDialog):
|
||||
|
||||
self.setWindowTitle("Item Settings")
|
||||
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","gear.svg"))
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
||||
self.svgGradient = QSvgWidget(self.gradPath)
|
||||
self.svgGradient.setFixedSize(QSize(64,64))
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class GuiProjectEditor(QDialog):
|
||||
self.setWindowTitle("Project Settings")
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.appPath,"graphics","gear.svg"))
|
||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
||||
self.svgGradient = QSvgWidget(self.gradPath)
|
||||
self.svgGradient.setFixedSize(QSize(64,64))
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ class NWSpellEnchant(NWSpellCheck):
|
||||
return
|
||||
|
||||
def setLanguage(self, theLang, projectDict=None):
|
||||
"""Load a dictionary for the language specified in the config. If that fails, we load a
|
||||
dummy dictionary so that lookups don't crash.
|
||||
"""
|
||||
try:
|
||||
if projectDict is None:
|
||||
self.theDict = enchant.Dict(theLang)
|
||||
@@ -40,7 +43,8 @@ class NWSpellEnchant(NWSpellCheck):
|
||||
logger.debug("Enchant spell checking for language %s loaded" % theLang)
|
||||
except:
|
||||
logger.error("Failed to load enchant spell checking for language %s" % theLang)
|
||||
self.theDict = None
|
||||
self.theDict = NWSpellEnchantDummy()
|
||||
|
||||
return
|
||||
|
||||
def checkWord(self, theWord):
|
||||
@@ -73,3 +77,19 @@ class NWSpellEnchant(NWSpellCheck):
|
||||
return retList
|
||||
|
||||
# END Class NWSpellEnchant
|
||||
|
||||
class NWSpellEnchantDummy:
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def check(self, theWord):
|
||||
return True
|
||||
|
||||
def suggest(self, theWord):
|
||||
return []
|
||||
|
||||
def add_to_pwl(self, theWord):
|
||||
return
|
||||
|
||||
# END Class NWSpellEnchantDummy
|
||||
|
||||
Reference in New Issue
Block a user