@@ -121,7 +121,7 @@ regularly tested on Windows 10.
|
||||
|
||||
The application can be started from the source folder with one of the commands, depending on your
|
||||
Python configuration:
|
||||
```
|
||||
```bash
|
||||
./novelWriter.py
|
||||
python novelWriter.py
|
||||
python3 novelWriter.py
|
||||
@@ -141,10 +141,9 @@ It is recommended that novelWriter runs with Qt 5.10 or later, and Python 3.6 or
|
||||
Qt as low as 5.2.1 and Python 3.4.3 has been tested, and worked in the past, but there are no
|
||||
guarantees that this will keep working as these are not a part of the test builds.
|
||||
|
||||
For the apt package manager on Debian systems, the following Python3 packages are needed:
|
||||
For the apt package manager on Debian/Ubuntu systems, the following Python3 packages are needed:
|
||||
|
||||
* `python3-pyqt5` for the GUI
|
||||
* `python3-pyqt5.qtsvg` may need to be installed separately
|
||||
* `python3-lxml` for writing project files
|
||||
|
||||
These are optional, but recommended:
|
||||
|
||||
@@ -66,10 +66,6 @@ The following Python packages are required to run novelWriter:
|
||||
|
||||
You can of course also install these packages from your operating system's package repository.
|
||||
|
||||
.. note::
|
||||
Sometimes the SVG graphics package for PyQt5 must be installed separately. It is usually called
|
||||
something like ``python3-pyqt5.qtsvg``.
|
||||
|
||||
PyQt/Qt should be at least 5.2.1, but ideally 5.10 or higher for nearly all features to work.
|
||||
Exporting to standard Markdown, for instance, requires PyQt/Qt 5.14. Searching using regular
|
||||
expressions requires 5.3, and for full Unicode support, 5.13.
|
||||
|
||||
+4
-5
@@ -27,13 +27,13 @@ helpMsg = (
|
||||
)
|
||||
|
||||
try:
|
||||
inOpts, inArgs = getopt.getopt(sys.argv[1:],shortOpt,longOpt)
|
||||
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"):
|
||||
if inOpt in ("-h", "--help"):
|
||||
print(helpMsg)
|
||||
sys.exit()
|
||||
elif inOpt in ("-d", "--debug"):
|
||||
@@ -41,7 +41,7 @@ for inOpt, inArg in inOpts:
|
||||
|
||||
# Run pip
|
||||
packList = ["pyinstaller"]
|
||||
with open("requirements.txt",mode="r") as reqFile:
|
||||
with open("requirements.txt", mode="r") as reqFile:
|
||||
for reqPack in reqFile:
|
||||
if len(reqPack.strip()) > 0:
|
||||
packList.append(reqPack)
|
||||
@@ -72,7 +72,7 @@ if buildWindowed:
|
||||
|
||||
instOpt.append("novelWriter.py")
|
||||
|
||||
import PyInstaller.__main__
|
||||
import PyInstaller.__main__ # noqa: F401
|
||||
PyInstaller.__main__.run(instOpt)
|
||||
|
||||
print("")
|
||||
@@ -82,4 +82,3 @@ print("##################")
|
||||
print("")
|
||||
print("If everything went well, the novelWriter executable should be in the folder named 'dist'")
|
||||
print("")
|
||||
|
||||
|
||||
+4
-4
@@ -4,10 +4,10 @@
|
||||
import sys
|
||||
|
||||
try:
|
||||
import PyQt5.QtWidgets
|
||||
import PyQt5.QtGui
|
||||
import PyQt5.QtCore
|
||||
except:
|
||||
import PyQt5.QtWidgets # noqa: F401
|
||||
import PyQt5.QtGui # noqa: F401
|
||||
import PyQt5.QtCore # noqa: F401
|
||||
except Exception:
|
||||
print("ERROR: Failed to load dependency python3-pyqt5")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
+6
-6
@@ -199,28 +199,28 @@ def main(sysArgs=None):
|
||||
|
||||
# Check Packages and Versions
|
||||
errorData = []
|
||||
errorCode = 0
|
||||
if sys.hexversion < 0x030403f0:
|
||||
errorData.append(
|
||||
"At least Python 3.4.3 is required, but 3.6 is highly recommended."
|
||||
)
|
||||
errorCode |= 4
|
||||
if CONFIG.verQtValue < 50200:
|
||||
errorData.append(
|
||||
"At least Qt5 version 5.2 is required, found %s." % CONFIG.verQtString
|
||||
)
|
||||
errorCode |= 8
|
||||
if CONFIG.verPyQtValue < 50200:
|
||||
errorData.append(
|
||||
"At least PyQt5 version 5.2 is required, found %s." % CONFIG.verPyQtString
|
||||
)
|
||||
|
||||
try:
|
||||
import PyQt5.QtSvg # noqa: F401
|
||||
except ImportError:
|
||||
errorData.append("Python module 'PyQt5.QtSvg' is missing.")
|
||||
errorCode |= 16
|
||||
|
||||
try:
|
||||
import lxml # noqa: F401
|
||||
except ImportError:
|
||||
errorData.append("Python module 'lxml' is missing.")
|
||||
errorCode |= 32
|
||||
|
||||
if errorData:
|
||||
if not testMode:
|
||||
@@ -236,7 +236,7 @@ def main(sysArgs=None):
|
||||
"<br> - ".join(errorData)
|
||||
))
|
||||
errApp.exec_()
|
||||
sys.exit(10 + len(errorData))
|
||||
sys.exit(errorCode)
|
||||
|
||||
# Finish initialising config
|
||||
CONFIG.initConfig(confPath, dataPath)
|
||||
|
||||
+2
-4
@@ -68,7 +68,6 @@ class Config:
|
||||
self.confPath = None # Folder where the config is saved
|
||||
self.confFile = None # The config file name
|
||||
self.dataPath = None # Folder where app data is stored
|
||||
self.homePath = None # The user's home folder
|
||||
self.lastPath = None # The last user-selected folder (browse dialogs)
|
||||
self.appPath = None # The full path to the novelwriter package folder
|
||||
self.appRoot = None # The full path to the novelwriter root folder
|
||||
@@ -257,8 +256,7 @@ class Config:
|
||||
logger.verbose("Data path: %s" % self.dataPath)
|
||||
|
||||
self.confFile = self.appHandle+".conf"
|
||||
self.homePath = os.path.expanduser("~")
|
||||
self.lastPath = self.homePath
|
||||
self.lastPath = os.path.expanduser("~")
|
||||
self.appPath = getattr(sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__)))
|
||||
self.appRoot = os.path.join(self.appPath, os.path.pardir)
|
||||
self.assetPath = os.path.join(self.appPath, "assets")
|
||||
@@ -268,7 +266,7 @@ class Config:
|
||||
self.appIcon = os.path.join(self.iconPath, "novelwriter.svg")
|
||||
|
||||
logger.verbose("App path: %s" % self.appPath)
|
||||
logger.verbose("Home path: %s" % self.homePath)
|
||||
logger.verbose("Last path: %s" % self.lastPath)
|
||||
|
||||
# If config folder does not exist, make it.
|
||||
# This assumes that the os config folder itself exists.
|
||||
|
||||
@@ -757,6 +757,10 @@ class NWProject():
|
||||
if self.projPath is None or self.projPath == "":
|
||||
return False
|
||||
|
||||
if self.projPath == os.path.expanduser("~"):
|
||||
# Don't make a mess in the user's home folder
|
||||
return False
|
||||
|
||||
self.projMeta = os.path.join(self.projPath, "meta")
|
||||
self.projCache = os.path.join(self.projPath, "cache")
|
||||
self.projContent = os.path.join(self.projPath, "content")
|
||||
|
||||
@@ -320,11 +320,12 @@ class GuiWritingStats(QDialog):
|
||||
|
||||
# Generate the file name
|
||||
if fileExt:
|
||||
fileName = "sessionStats.%s" % fileExt
|
||||
saveDir = self.mainConf.lastPath
|
||||
savePath = os.path.join(saveDir, fileName)
|
||||
saveDir = self.mainConf.lastPath
|
||||
if not os.path.isdir(saveDir):
|
||||
saveDir = self.mainConf.homePath
|
||||
saveDir = os.path.expanduser("~")
|
||||
|
||||
fileName = "sessionStats.%s" % fileExt
|
||||
savePath = os.path.join(saveDir, fileName)
|
||||
|
||||
dlgOpt = QFileDialog.Options()
|
||||
dlgOpt |= QFileDialog.DontUseNativeDialog
|
||||
|
||||
@@ -135,7 +135,7 @@ setuptools.setup(
|
||||
"console_scripts" : ["novelWriter-cli=nw:main"],
|
||||
"gui_scripts" : ["novelWriter=nw:main"],
|
||||
},
|
||||
packages = setuptools.find_packages(exclude=["docs","tests","sample"]),
|
||||
packages = setuptools.find_packages(exclude=["docs", "tests", "sample"]),
|
||||
include_package_data = True,
|
||||
package_data = {"": ["*.conf"]},
|
||||
project_urls = {
|
||||
|
||||
+4
-2
@@ -85,7 +85,6 @@ def testLaunch(qtbot, monkeypatch, nwFuncTemp, nwTemp):
|
||||
assert ex.value.code == 2
|
||||
|
||||
# Simulate import error
|
||||
monkeypatch.setitem(sys.modules, "PyQt5.QtSvg", None)
|
||||
monkeypatch.setitem(sys.modules, "lxml", None)
|
||||
monkeypatch.setattr("sys.hexversion", 0x0)
|
||||
monkeypatch.setattr("nw.CONFIG.verQtValue", 50000)
|
||||
@@ -96,7 +95,10 @@ def testLaunch(qtbot, monkeypatch, nwFuncTemp, nwTemp):
|
||||
)
|
||||
nwGUI.closeMain()
|
||||
nwGUI.close()
|
||||
assert ex.value.code == 15
|
||||
assert ex.value.code & 4 == 4 # Python version not satisfied
|
||||
assert ex.value.code & 8 == 8 # Qt version not satisfied
|
||||
assert ex.value.code & 16 == 16 # PyQt version not satisfied
|
||||
assert ex.value.code & 32 == 32 # lxml package missing
|
||||
monkeypatch.undo()
|
||||
|
||||
@pytest.mark.gui
|
||||
|
||||
Reference in New Issue
Block a user