diff --git a/README.md b/README.md index 1dd83e67..a5e6aea7 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/docs/source/int_started.rst b/docs/source/int_started.rst index 549a57ef..e96a0285 100644 --- a/docs/source/int_started.rst +++ b/docs/source/int_started.rst @@ -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. diff --git a/install.py b/install.py index 4bd4c0e7..ea7c976d 100755 --- a/install.py +++ b/install.py @@ -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("") - diff --git a/novelWriter.py b/novelWriter.py index 1d4b711a..d6c7deb7 100755 --- a/novelWriter.py +++ b/novelWriter.py @@ -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) diff --git a/nw/__init__.py b/nw/__init__.py index aa755a2e..5aa259e9 100644 --- a/nw/__init__.py +++ b/nw/__init__.py @@ -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): "
 - ".join(errorData) )) errApp.exec_() - sys.exit(10 + len(errorData)) + sys.exit(errorCode) # Finish initialising config CONFIG.initConfig(confPath, dataPath) diff --git a/nw/config.py b/nw/config.py index c5512783..5f4a1300 100644 --- a/nw/config.py +++ b/nw/config.py @@ -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. diff --git a/nw/core/project.py b/nw/core/project.py index 953d7879..46e37202 100644 --- a/nw/core/project.py +++ b/nw/core/project.py @@ -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") diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index d45b3726..165e7fd9 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -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 diff --git a/setup.py b/setup.py index e3ce209c..515c2bfd 100755 --- a/setup.py +++ b/setup.py @@ -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 = { diff --git a/tests/test_gui.py b/tests/test_gui.py index 3bffd372..ab732fca 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -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