Merge branch 'release' into dev

This commit is contained in:
Veronica K. B. Olsen
2021-02-05 23:08:48 +01:00
9 changed files with 110 additions and 311 deletions
+1 -13
View File
@@ -40,7 +40,6 @@ Contributions to this project are welcome. However, please read the
[Contributing Guide](https://github.com/vkbo/novelWriter/blob/main/CONTRIBUTING.md) before
submitting larger additions ot changes to this project.
# Key Features
Some features of novelWriter are listed below. Consult the
@@ -82,7 +81,6 @@ with limitations to formatting.
The HTML format is well suited for file conversion tools and import into other text editors.
### Colour Themes
The editor has syntax highlighting for the features it supports, and includes a set of different
@@ -107,7 +105,6 @@ project tree. These are mostly to help the user track what they contain, but the
impact on the format of the exported document. See the
[documentation](https://novelwriter.readthedocs.io) for further details.
### Project Notes
Supporting note files can be added for the story plot, characters, locations, story timeline, etc.
@@ -122,13 +119,11 @@ connects to the plot, and which characters, etc. occur in them. In addition, the
are clickable in the document view pane, and control-clickable in the editor. They make it possible
to quickly navigate between the documents while editing.
# Installing and Running
For install instructions, please check the [documentation](https://novelwriter.readthedocs.io/) in
the [Getting Started](https://novelwriter.readthedocs.io/en/latest/int_started.html) section.
## TLDR Instructions
If you want to run novelWriter directly from the source code, you must run the `novelWriter.py`
@@ -138,7 +133,6 @@ file from command line. For installations on Linux, macOS or Windows, see below.
below on some systems. You may also want to add the `--user` flag for `pip` to install in your user
space only.
### Install from PyPi
novelWriter is available on [pypi.org](https://pypi.org/project/novelWriter/), and can be installed
@@ -158,7 +152,6 @@ novelWriter
Make sure the install location for pip is in your PATH variable. This is not always the case by
default.
### Setup on Linux
If you're installing from source, the following commands will set up novelWriter on Linux:
@@ -171,7 +164,6 @@ python setup.py xdg-install
This should make novelWriter available as a regular application on your system, with a launceher
icon, and file association with novelWriter project files.
### Setup on macOS
If you're installing from source, the following commands will set up novelWriter on macOS:
@@ -188,7 +180,6 @@ line with:
novelWriter
```
### Setup on Windows
For Windows, first ensure that you have Python installed. If not, get it from
@@ -199,8 +190,7 @@ Then, download the `novelWriter-x.y.z-minimal.zip` file, where `x.y.z` is the ve
the [releases](https://github.com/vkbo/novelWriter/releases) page. You can extract it to wherever
you want to keep novelWriter on your PC, and run the `setup_windows.bat` file in it
(double-clicking it should work). This will install the necessary dependencies from
[pypi,org](https://pypi.org/) and create desktop and start menu icons.
[pypi.org](https://pypi.org/) and create desktop and start menu icons.
## Debugging
@@ -208,7 +198,6 @@ If you need to debug novelWriter, you must run it from command line. It takes a
which can be listed with the switch `--help`. The `--info`, `--debug` or `--verbose` flags are
particularly useful for increasing logging output for debugging.
# Licenses
This is Open Source software, and novelWriter is licensed under GPLv3. See the
@@ -235,7 +224,6 @@ Bundled assets have the following licenses:
the main repo is available at
[sdras/night-owl-vscode-theme](https://github.com/sdras/night-owl-vscode-theme).
# Screenshot
**novelWriter with default system theme:**
+31 -16
View File
@@ -7,10 +7,11 @@ Setup on Windows
This is a brief guide to how you can get novelWriter running on a Windows computer.
Unlike other operating systems, Windows does not come prepared with an environment to run Python
applications, so you must first install Python. After that, running novelWriter is straightfoeward.
applications, so you must first install Python. After that, running novelWriter is straightforward.
If you have any problems, you can always open a question on the project's discussions_ page. This
requires a GitHub account.
.. tip::
If you have any problems, you can always open a question on the project's discussions_ page.
This requires a GitHub account.
.. _discussions: https://github.com/vkbo/novelWriter/discussions
@@ -20,11 +21,15 @@ requires a GitHub account.
Using the Installer
===================
The installer for Windows is no longer provided. You can still create it yourself if you want to.
It can be generated with the provided ``setup.py`` script. use the script's ``help`` command to get
further instructions.
The installer for Windows is no longer provided. See the `installer issue`_ for more info on why.
You can still create the installer yourself if you want to. It can be generated with the provided
``setup.py`` script. use the script's ``help`` command to get further instructions.
Please use the "Running from Source" option below instead.
Please use the "Running from Source" option below instead. It has been improved and a script has
been added that does nearly the same thing.
.. _installer issue: https://github.com/vkbo/novelWriter/issues/640
.. _a_setup_win_source:
@@ -33,12 +38,18 @@ Running from Source
===================
To run novelWriter from source, download the latest source zip file from the release page on
GitHub_ or the `main website`_. The file named ``novelWriter-x.y.z-minimal.zip``, where ``x.y.z``
is the version number, is ideal for this. You can also download the full source.
GitHub_, or from the `main website`_. You can download the "Minimal Windows" zip file. It is a
minimal version of the source that contains only the files needed for running on Windows. You can
also download the full source if you wish.
In order to make novelWriter run on your system, you must first have Python installed (Step 1).
Thereafter, a script will do the rest of the job (Step 2). or you can do it yourself manually if
you wish to.
Thereafter, a script will do the rest of the job (Step 2). Alternatively, you can run this step
manually from the command prompt if you wish to.
.. tip::
If your system already has all the dependencies installed, you can run novelWriter directly from
the extracted folder by double-clicking the ``novelWriter.pyw`` file. However, running the
script also adds start icons.
.. _GitHub: https://github.com/vkbo/novelWriter/releases
.. _main website: https://novelwriter.io
@@ -66,13 +77,17 @@ Step 2: Dependencies and Icons
**Alternative A: By Script**
Open the folder where you extracted the novelWriter source, and double-click the file named
``setup_windows`` or ``setup_windows.bat``. This should open a command line window and run the
setup script to install dependencies, and add desktop and start menu icons. It will also check that
it can find Python from Step 1.
``setup_windows.bat``. This should open a command line window and run the setup script to install
dependencies, and add desktop and start menu icons.
The script will also check that it can find Python on your system and alert you if it cannot run
it. If you are sure you have installed it, but the script cannot find it, you probably didn't
install it with the "Add Python to PATH" option mentioned in Step 1.
.. note::
If you upgrade Python to a newer version and the path to ``pythonw.exe`` changes, you may need
to run this script again.
If you upgrade Python to a newer version and the path to ``pythonw.exe`` has therefore changed,
you may need to run this script again. You can also run it to upgrade dependencies to the latest
version.
**Alternative B: Manual Installation**
+6 -5
View File
@@ -1,11 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
novelWriter Terminal Start Script
===================================
The main start script for the terminal
novelWriter Start Script
==========================
"""
import os
import sys
try:
@@ -13,9 +12,11 @@ try:
import PyQt5.QtGui # noqa: F401
import PyQt5.QtCore # noqa: F401
except Exception:
print("ERROR: Failed to load dependency python3-pyqt5")
print("ERROR: Failed to load dependency PyQt5")
sys.exit(1)
os.curdir = os.path.abspath(os.path.dirname(__file__))
if __name__ == "__main__":
import nw
nw.main(sys.argv[1:])
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
novelWriter Windows Start Script
==================================
The main start script for Windows GUI
"""
import os
os.curdir = os.path.abspath(os.path.dirname(__file__))
if __name__ == "__main__":
import nw
nw.main()
+60 -189
View File
@@ -234,11 +234,11 @@ def buildSampleZip():
# Make Minimal Package (minimal-zip)
##
def makeMinimalPackage():
def makeMinimalPackage(targetOS):
"""Pack the core source file in a single zip file.
"""
from nw import __version__
from zipfile import ZipFile
from zipfile import ZipFile, ZIP_DEFLATED
# Make sample.zip first
try:
@@ -256,36 +256,53 @@ def makeMinimalPackage():
if not os.path.isdir("dist"):
os.mkdir("dist")
outFile = os.path.join("dist", "novelWriter-%s-minimal.zip" % __version__)
if targetOS == OS_LINUX:
targName = "-linux"
elif targetOS == OS_DARWIN:
targName = "-darwin"
elif targetOS == OS_WIN:
targName = "-win"
else:
targName = ""
outFile = os.path.join("dist", f"novelWriter-{__version__}-minimal{targName}.zip")
if os.path.isfile(outFile):
os.unlink(outFile)
rootFiles = [
"LICENSE.md",
"README.md",
"CHANGELOG.md",
"novelWriter.pyw",
"requirements.txt",
"setup.py",
"setup_windows.bat",
]
rootFiles = ["LICENSE.md", "README.md", "CHANGELOG.md", "requirements.txt", "setup.py"]
with ZipFile(outFile, "w", compression=ZIP_DEFLATED, compresslevel=9) as zipObj:
if targetOS != OS_WIN:
for nRoot, _, nFiles in os.walk("setup"):
print("Adding Folder: %s [%d files]" % (nRoot, len(nFiles)))
for aFile in nFiles:
zipObj.write(os.path.join(nRoot, aFile))
with ZipFile(outFile, "w") as zipObj:
for nRoot, _, nFiles in os.walk("nw"):
if nRoot.endswith("__pycache__"):
print("Skipping: %s" % nRoot)
print("Skipping Folder: %s" % nRoot)
continue
print("Compressing: %s [%d files]" % (nRoot, len(nFiles)))
print("Adding Folder: %s [%d files]" % (nRoot, len(nFiles)))
for aFile in nFiles:
if aFile.endswith(".pyc"):
print("Skipping: %s" % aFile)
print("Skipping File: %s" % aFile)
continue
zipObj.write(os.path.join(nRoot, aFile))
if targetOS == OS_WIN:
zipObj.write("novelWriter.py", "novelWriter.pyw")
print("Adding File: novelWriter.pyw")
zipObj.write("setup_windows.bat")
print("Adding File: setup_windows.bat")
else:
zipObj.write("novelWriter.py")
print("Adding File: novelWriter.py")
for aFile in rootFiles:
assert os.path.isfile(aFile)
print("Compressing: %s" % aFile)
print("Adding File: %s" % aFile)
zipObj.write(aFile)
print("")
@@ -472,127 +489,6 @@ def makeSimplePackage(embedPython):
return
##
# Run PyInstaller on Package (freeze, onefile)
##
def freezePackage(buildWindowed, oneFile, makeSetup, hostOS):
"""Run PyInstaller to freeze the packages. This assumes all
dependencies are already in place.
"""
try:
import PyInstaller.__main__ # noqa: E402
except ImportError:
print(
"ERROR: Package 'pyinstaller' is missing on this system.\n"
" Please run 'pip install --user pyinstaller'."
)
sys.exit(1)
print("")
print("Running PyInstaller")
print("===================")
print("")
if hostOS == OS_WIN:
dotDot = ";"
else:
dotDot = ":"
sys.modules["FixTk"] = None
instOpt = [
"--name=novelWriter",
"--clean",
"--add-data=%s%s%s" % (os.path.join("nw", "assets"), dotDot, "assets"),
"--icon=%s" % os.path.join("nw", "assets", "icons", "novelwriter.ico"),
"--exclude-module=PyQt5.QtQml",
"--exclude-module=PyQt5.QtBluetooth",
"--exclude-module=PyQt5.QtDBus",
"--exclude-module=PyQt5.QtMultimedia",
"--exclude-module=PyQt5.QtMultimediaWidgets",
"--exclude-module=PyQt5.QtNetwork",
"--exclude-module=PyQt5.QtNetworkAuth",
"--exclude-module=PyQt5.QtNfc",
"--exclude-module=PyQt5.QtQuick",
"--exclude-module=PyQt5.QtQuickWidgets",
"--exclude-module=PyQt5.QtRemoteObjects",
"--exclude-module=PyQt5.QtSensors",
"--exclude-module=PyQt5.QtSerialPort",
"--exclude-module=PyQt5.QtSql",
"--exclude-module=FixTk",
"--exclude-module=tcl",
"--exclude-module=tk",
"--exclude-module=_tkinter",
"--exclude-module=tkinter",
"--exclude-module=Tkinter",
]
if buildWindowed:
instOpt.append("--windowed")
if oneFile and not makeSetup:
instOpt.append("--onefile")
else:
instOpt.append("--onedir")
instOpt.append("novelWriter.py")
# Make sample.zip first
try:
buildSampleZip()
except Exception as e:
print("Failed with error:")
print(str(e))
sys.exit(1)
PyInstaller.__main__.run(instOpt)
if not oneFile:
# These files are not needed, and take up a fair bit of space.
delFiles = []
if hostOS == OS_WIN:
delFiles = [
"Qt5DBus.dll",
"Qt5Network.dll",
"Qt5Qml.dll",
"Qt5QmlModels.dll",
"Qt5Quick.dll",
"Qt5Quick3D.dll",
"Qt5Quick3DAssetImport.dll",
"Qt5Quick3DRender.dll",
"Qt5Quick3DRuntimeRender.dll",
"Qt5Quick3DUtils.dll",
"Qt5Sql.dll"
]
elif hostOS == OS_LINUX:
delFiles = [
"libQt5DBus.so.5",
"libQt5Network.so.5",
"libQt5Qml.so.5",
"libQt5QmlModels.so.5",
"libQt5Quick.so.5",
"libQt5Quick3D.so.5",
"libQt5Quick3DAssetImport.so.5",
"libQt5Quick3DRender.so.5",
"libQt5Quick3DRuntimeRender.so.5",
"libQt5Quick3DUtils.so.5",
"libQt5Sql.so.5"
]
distDir = os.path.join(os.getcwd(), "dist", "novelWriter")
for delFile in delFiles:
delPath = os.path.join(distDir, delFile)
if os.path.isfile(delPath):
print("Deleting file: %s" % delPath)
os.unlink(delPath)
print("")
print("Build Finished")
print("")
print("The novelWriter executable should be in the folder named 'dist'")
print("")
return
# =============================================================================================== #
# General Installers
# =============================================================================================== #
@@ -871,9 +767,8 @@ def winInstall():
# Inno Setup Builder (setup-exe, setup-pyz)
##
def innoSetup(setupType):
"""Run the Inno Setup tool to build a setup.exe file for Windows based on either a pyinstaller
freeze package (exe) or a zipapp package (pyz).
def innoSetup():
"""Run the Inno Setup tool to build a setup.exe file for Windows based on the pyz package.
"""
print("")
print("Running Inno Setup")
@@ -882,7 +777,7 @@ def innoSetup(setupType):
# Read the iss template
issData = ""
with open(os.path.join("setup", "win_setup_%s.iss" % setupType), mode="r") as inFile:
with open(os.path.join("setup", "win_setup_pyz.iss"), mode="r") as inFile:
issData = inFile.read()
import nw # noqa: E402
@@ -908,7 +803,6 @@ def innoSetup(setupType):
if __name__ == "__main__":
"""Parse command line options and run the commands.
"""
# Detect OS
if sys.platform.startswith("linux"):
hostOS = OS_LINUX
@@ -921,6 +815,19 @@ if __name__ == "__main__":
else:
hostOS = OS_NONE
# Set Target OS
if "--target-linux" in sys.argv:
sys.argv.remove("--target-linux")
targetOS = OS_LINUX
elif "--target-darwin" in sys.argv:
sys.argv.remove("--target-darwin")
targetOS = OS_DARWIN
elif "--target-win" in sys.argv:
sys.argv.remove("--target-win")
targetOS = OS_WIN
else:
targetOS = hostOS
helpMsg = (
"\n"
"novelWriter Setup Tool\n"
@@ -929,6 +836,9 @@ if __name__ == "__main__":
"This tool provides setup and build commands for installing or distibuting novelWriter\n"
"as a package on Linux, Mac and Windows. The available options are as follows:\n"
"\n"
"Some of the commands can be targeted towards a different OS than the host OS. To target\n"
"the command, add one of '--target-linux', '--target-darwin' or '--target-win'.\n"
"\n"
"General:\n"
"\n"
" help Print the help message.\n"
@@ -945,15 +855,12 @@ if __name__ == "__main__":
"Python Packaging:\n"
"\n"
" minimal-zip Creates a minimal zip file of the core application without all the\n"
" other source files.\n"
" other source files. Accepts a target OS flag.\n"
" pack-pyz Creates a pyz package in a folder with all dependencies using the\n"
" zipapp tool. On Windows, python embeddable is added to the folder.\n"
" freeze Freeze the package and produces a folder with all dependencies using\n"
" the pyinstaller tool. This option is not designed for a specific OS.\n"
" onefile Build a standalone executable with all dependencies bundled using the\n"
" pyinstaller tool. Implies 'freeze', cannot be used with 'setup-exe'.\n"
" setup-pyz Build a Windows installer from a zipapp package using Inno Setup.\n"
"\n"
"General Installers:\n"
"System Install:\n"
"\n"
" install Installs novelWriter to the system's Python install location. Run as \n"
" root or with sudo for system-wide install, or as user for single user \n"
@@ -961,20 +868,10 @@ if __name__ == "__main__":
" xdg-install Install launcher and icons for freedesktop systems. Run as root or \n"
" with sudo for system-wide install, or as user for single user install.\n"
" win-install Install desktop and start menu icons for Windows systems.\n"
"\n"
"Windows Installers:\n"
"\n"
" setup-exe Build a Windows installer from a pyinstaller freeze package using Inno\n"
" Setup. This option automatically disables 'onefile'.\n"
" setup-pyz Build a Windows installer from a zipapp package using Inno Setup.\n"
)
# Flags and Variables
buildWindowed = True
oneFile = False
makeSetupExe = False
makeSetupPyz = False
doFreeze = False
simplePack = False
embedPython = False
@@ -1010,7 +907,7 @@ if __name__ == "__main__":
if "minimal-zip" in sys.argv:
sys.argv.remove("minimal-zip")
makeMinimalPackage()
makeMinimalPackage(targetOS)
if "pack-pyz" in sys.argv:
sys.argv.remove("pack-pyz")
@@ -1018,15 +915,6 @@ if __name__ == "__main__":
if hostOS == OS_WIN:
embedPython = True
if "freeze" in sys.argv:
sys.argv.remove("freeze")
doFreeze = True
if "onefile" in sys.argv:
sys.argv.remove("onefile")
doFreeze = True
oneFile = True
# General Installers
# ==================
@@ -1051,23 +939,12 @@ if __name__ == "__main__":
print("ERROR: Command 'win-install' can only be used on Windows")
sys.exit(1)
# Windows Setup Installers
# ========================
if "setup-exe" in sys.argv:
sys.argv.remove("setup-exe")
if hostOS == OS_WIN:
oneFile = False
makeSetupExe = True
makeSetupPyz = False
else:
print("Error: Command 'setup-exe' for Inno Setup is Windows only.")
sys.exit(1)
# Windows Setup Installer
# =======================
if "setup-pyz" in sys.argv:
sys.argv.remove("setup-pyz")
if hostOS == OS_WIN:
makeSetupExe = False
makeSetupPyz = True
else:
print("Error: Command 'setup-pyz' for Inno Setup is Windows only.")
@@ -1081,14 +958,8 @@ if __name__ == "__main__":
if simplePack:
makeSimplePackage(embedPython)
if doFreeze:
freezePackage(buildWindowed, oneFile, makeSetupExe, hostOS)
if makeSetupExe:
innoSetup("exe")
if makeSetupPyz:
innoSetup("pyz")
innoSetup()
if len(sys.argv) <= 1:
# Nothing more to do
+12 -14
View File
@@ -8,9 +8,13 @@ The root folder of the repository contains two scripts for setup and install:
The `setup.py` is a standard Python setup script with a couple of additional
options:
Some of the commands can be targeted towards a different OS than the host OS.
To target the command, add one of `--target-linux`, `--target-darwin` or
`--target-win`.
### General
`help` Print the help message
`help` Print the help message.
`pip` Install all package dependencies for novelWriter using pip.
@@ -26,16 +30,15 @@ creating sample projects in the in-app New Project Wizard.
### Python Packaging
`minimal-zip` Creates a minimal zip file of the core application without all
the other source files.
`pack-pyz` Creates a pyz package in a folder with all dependencies using the
zipapp tool. This option is intended for Windows deployment.
zipapp tool. On Windows, python embeddable is added to the folder.
`freeze` Freeze the package and produces a folder with all dependencies using
the pyinstaller tool. This option is not designed for a specific OS.
`setup-pyz` Build a Windows installer from a zipapp package using Inno Setup.
`onefile` Build a standalone executable with all dependencies bundled using
the pyinstaller tool. Implies `freeze`, cannot be used with `setup-exe`
### General Installers
### System Install
`install` Installs novelWriter to the system's Python install location. Run
as root or with sudo for system-wide install, or as user for single user
@@ -44,9 +47,4 @@ install.
`xdg-install` Install launcher and icons for freedesktop systems. Run as root
or with sudo for system-wide install, or as user for single user install.
### Windows Installers
`setup-exe` Build a Windows installer from a pyinstaller freeze package using
Inno Setup. This option automatically disables `onefile`.
`setup-pyz` Build a Windows installer from a zipapp package using Inno Setup.
`win-install` Install desktop and start menu icons for Windows systems.
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

-59
View File
@@ -1,59 +0,0 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define nwAppDir "%%dir%%\dist"
#define nwAppName "novelWriter"
#define nwAppVersion "%%version%%"
#define nwAppPublisher "novelWriter"
#define nwAppURL "http://novelWriter.io"
#define nwAppExeName "novelWriter.exe"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{459A75D0-951F-4932-9809-6002EC8E733E}
AppName={#nwAppName}
AppVersion={#nwAppVersion}
AppVerName={#nwAppName} {#nwAppVersion}
AppPublisher={#nwAppPublisher}
AppPublisherURL={#nwAppURL}
AppSupportURL={#nwAppURL}
AppUpdatesURL={#nwAppURL}
DefaultDirName={autopf}\{#nwAppName}
DisableProgramGroupPage=yes
; The [Icons] "quicklaunchicon" entry uses {userappdata} but its [Tasks] entry has a proper IsAdminInstallMode Check.
UsedUserAreasWarning=no
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
OutputDir={#nwAppDir}
OutputBaseFilename=novelwriter-{#nwAppVersion}-win10-amd64-setup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
ArchitecturesInstallIn64BitMode=x64
ChangesAssociations=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 6.1; Check: not IsAdminInstallMode
[Files]
Source: "{#nwAppDir}\novelWriter\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{autoprograms}\{#nwAppName}"; Filename: "{app}\{#nwAppExeName}"
Name: "{autodesktop}\{#nwAppName}"; Filename: "{app}\{#nwAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#nwAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(nwAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Registry]
Root: HKA; Subkey: "Software\Classes\.nwx\OpenWithProgids"; ValueType: string; ValueName: "novelWriterProject.nwx"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx"; ValueType: string; ValueName: ""; ValueData: "novelWriter Project File"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\assets\icons\x-novelwriter-project.ico"
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#nwAppExeName}"" ""%1"""
Root: HKA; Subkey: "Software\Classes\Applications\{#nwAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".nwx"; ValueData: ""