@@ -6,6 +6,7 @@
|
|||||||
*.spec
|
*.spec
|
||||||
*.egg-info
|
*.egg-info
|
||||||
setup.iss
|
setup.iss
|
||||||
|
novelwriter.desktop
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
/docs/build/
|
/docs/build/
|
||||||
|
|||||||
@@ -104,8 +104,10 @@ If you want to run directly from the source, the application can be started with
|
|||||||
|
|
||||||
You can also create a launcher for running directly from source with:
|
You can also create a launcher for running directly from source with:
|
||||||
```bash
|
```bash
|
||||||
sudo python3 setup.py launcher
|
python3 setup.py xdg-install
|
||||||
```
|
```
|
||||||
|
This will install the launcher and icons for the current user.
|
||||||
|
To install them system-wide, run the above command with `sudo` or as root.
|
||||||
|
|
||||||
For more install options, see [Build and Install novelWriter](setup/README.md).
|
For more install options, see [Build and Install novelWriter](setup/README.md).
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import setuptools
|
|
||||||
|
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
# Qt Assistant Documentation Builder
|
# Qt Assistant Documentation Builder
|
||||||
@@ -140,14 +139,17 @@ def buildSampleZip():
|
|||||||
# Create Launcher
|
# Create Launcher
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def makeLauncherLinux():
|
def xdgInstall():
|
||||||
"""Will attempt to install icons and make a launcher.
|
"""Will attempt to install icons and make a launcher.
|
||||||
"""
|
"""
|
||||||
print("")
|
print("")
|
||||||
print("Creating Launcher")
|
print("XDG Install")
|
||||||
print("=================")
|
print("===========")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
# Find Executable(s)
|
||||||
|
# ==================
|
||||||
|
|
||||||
exOpts = []
|
exOpts = []
|
||||||
|
|
||||||
testExec = shutil.which("novelWriter")
|
testExec = shutil.which("novelWriter")
|
||||||
@@ -185,95 +187,92 @@ def makeLauncherLinux():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
print("Using executable: %s " % useExec)
|
print("Using executable: %s " % useExec)
|
||||||
|
print("")
|
||||||
|
|
||||||
|
# Create and Install Launcher
|
||||||
|
# ===========================
|
||||||
|
|
||||||
# Read the Template
|
|
||||||
desktopData = ""
|
desktopData = ""
|
||||||
with open(os.path.join("setup", "novelwriter.desktop"), mode="r") as inFile:
|
with open("./setup/novelwriter.desktop", mode="r") as inFile:
|
||||||
desktopData = inFile.read()
|
desktopData = inFile.read()
|
||||||
|
|
||||||
desktopData = desktopData.replace(r"%%exec%%", useExec)
|
desktopData = desktopData.replace(r"%%exec%%", useExec)
|
||||||
|
with open("./novelwriter.desktop", mode="w+") as outFile:
|
||||||
|
outFile.write(desktopData)
|
||||||
|
|
||||||
desktopFile = "/usr/share/applications/novelwriter.desktop"
|
exCode = subprocess.call(
|
||||||
try:
|
["xdg-desktop-menu", "install", "--novendor", "./novelwriter.desktop"]
|
||||||
with open(desktopFile, mode="w+") as outFile:
|
)
|
||||||
outFile.write(desktopData)
|
if exCode == 0:
|
||||||
print("Wrote file: %s" % desktopFile)
|
print("Installed menu desktop file")
|
||||||
except Exception as e:
|
else:
|
||||||
print("Error: Could not write novelwriter.desktop file.")
|
print(f"Error {exCode}: Could not install menu desktop file")
|
||||||
print(str(e))
|
|
||||||
sys.exit(1)
|
exCode = subprocess.call(
|
||||||
|
["xdg-desktop-icon", "install", "--novendor", "./novelwriter.desktop"]
|
||||||
|
)
|
||||||
|
if exCode == 0:
|
||||||
|
print("Installed icon desktop file")
|
||||||
|
else:
|
||||||
|
print(f"Error {exCode}: Could not install icon desktop file")
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Copy Icons
|
# Install MimeType
|
||||||
|
# ================
|
||||||
|
|
||||||
iconDirs = [
|
exCode = subprocess.call([
|
||||||
"/usr/share/icons/hicolor/24x24/apps",
|
"xdg-mime", "install",
|
||||||
"/usr/share/icons/hicolor/48x48/apps",
|
"./setup/mime/x-novelwriter-project.xml"
|
||||||
"/usr/share/icons/hicolor/96x96/apps",
|
])
|
||||||
"/usr/share/icons/hicolor/256x256/apps",
|
if exCode == 0:
|
||||||
"/usr/share/icons/hicolor/512x512/apps",
|
print("Installed mimetype")
|
||||||
"/usr/share/icons/hicolor/scalable/apps",
|
else:
|
||||||
"/usr/share/icons/hicolor/scalable/mimetypes",
|
print(f"Error {exCode}: Could not install mimetype")
|
||||||
]
|
|
||||||
for iconDir in iconDirs:
|
|
||||||
if not os.path.isdir:
|
|
||||||
try:
|
|
||||||
os.mkdir(iconDir)
|
|
||||||
print("Created folder: %s" % iconDir)
|
|
||||||
except Exception as e:
|
|
||||||
print("Error: Could not make folder: %s" % iconDir)
|
|
||||||
print(str(e))
|
|
||||||
|
|
||||||
copyList = [(
|
|
||||||
"setup/icons/24x24/novelwriter.png",
|
|
||||||
"/usr/share/icons/hicolor/24x24/apps/novelwriter.png"
|
|
||||||
), (
|
|
||||||
"setup/icons/48x48/novelwriter.png",
|
|
||||||
"/usr/share/icons/hicolor/48x48/apps/novelwriter.png"
|
|
||||||
), (
|
|
||||||
"setup/icons/96x96/novelwriter.png",
|
|
||||||
"/usr/share/icons/hicolor/96x96/apps/novelwriter.png"
|
|
||||||
), (
|
|
||||||
"setup/icons/256x256/novelwriter.png",
|
|
||||||
"/usr/share/icons/hicolor/256x256/apps/novelwriter.png"
|
|
||||||
), (
|
|
||||||
"setup/icons/512x512/novelwriter.png",
|
|
||||||
"/usr/share/icons/hicolor/512x512/apps/novelwriter.png"
|
|
||||||
), (
|
|
||||||
"setup/icons/novelwriter.svg",
|
|
||||||
"/usr/share/icons/hicolor/scalable/apps/novelwriter.svg"
|
|
||||||
), (
|
|
||||||
"setup/icons/x-novelwriter-project.svg",
|
|
||||||
"/usr/share/icons/hicolor/scalable/mimetypes/application-x-novelwriter-project.svg"
|
|
||||||
), (
|
|
||||||
"setup/mime/x-novelwriter-project.xml",
|
|
||||||
"/usr/share/mime/packages/x-novelwriter-project.xml"
|
|
||||||
)]
|
|
||||||
for srcFile, dstFile in copyList:
|
|
||||||
try:
|
|
||||||
shutil.copyfile(srcFile, dstFile)
|
|
||||||
print("Copied file to: %s" % dstFile)
|
|
||||||
except Exception as e:
|
|
||||||
print("Error: Could not copy file: %s" % srcFile)
|
|
||||||
print(str(e))
|
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Update System
|
# Install Icons
|
||||||
try:
|
# =============
|
||||||
subprocess.call(["update-mime-database", "/usr/share/mime/"])
|
|
||||||
print("Updated mime database.")
|
|
||||||
except Exception as e:
|
|
||||||
print("Error: Filed to update mime database.")
|
|
||||||
print(str(e))
|
|
||||||
|
|
||||||
try:
|
sizeArr = ["16", "22", "24", "32", "48", "64", "96", "128", "256", "512"]
|
||||||
subprocess.call(["update-icon-caches", "/usr/share/icons/*"])
|
|
||||||
print("Updated icon cache.")
|
# App Icon
|
||||||
except Exception as e:
|
for aSize in sizeArr:
|
||||||
print("Error: Filed to update icon cache.")
|
exCode = subprocess.call([
|
||||||
print(str(e))
|
"xdg-icon-resource", "install",
|
||||||
|
"--novendor", "--noupdate",
|
||||||
|
"--context", "apps",
|
||||||
|
"--size", aSize,
|
||||||
|
f"./setup/icons/scaled/icon-novelwriter-{aSize}.png",
|
||||||
|
"novelwriter"
|
||||||
|
])
|
||||||
|
if exCode == 0:
|
||||||
|
print(f"Installed app icon size {aSize}")
|
||||||
|
else:
|
||||||
|
print(f"Error {exCode}: Could not install app icon size {aSize}")
|
||||||
|
|
||||||
|
# Mimetype
|
||||||
|
for aSize in sizeArr:
|
||||||
|
exCode = subprocess.call([
|
||||||
|
"xdg-icon-resource", "install",
|
||||||
|
"--noupdate",
|
||||||
|
"--context", "mimetypes",
|
||||||
|
"--size", aSize,
|
||||||
|
f"./setup/icons/scaled/mime-novelwriter-{aSize}.png",
|
||||||
|
"application-x-novelwriter-project"
|
||||||
|
])
|
||||||
|
if exCode == 0:
|
||||||
|
print(f"Installed mime icon size {aSize}")
|
||||||
|
else:
|
||||||
|
print(f"Error {exCode}: Could not install mime icon size {aSize}")
|
||||||
|
|
||||||
|
# Update Cache
|
||||||
|
exCode = subprocess.call(["xdg-icon-resource", "forceupdate"])
|
||||||
|
if exCode == 0:
|
||||||
|
print("Updated icon cache")
|
||||||
|
else:
|
||||||
|
print(f"Error {exCode}: Could not update icon cache")
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
print("Done!")
|
print("Done!")
|
||||||
@@ -293,10 +292,10 @@ if __name__ == "__main__":
|
|||||||
"======================\n"
|
"======================\n"
|
||||||
"This tool provides some additional setup commands for novelWriter.\n"
|
"This tool provides some additional setup commands for novelWriter.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"help Print the help message.\n"
|
"help Print the help message.\n"
|
||||||
"qthelp Build the help documentation for use with the QtAssistant.\n"
|
"qthelp Build the help documentation for use with the QtAssistant.\n"
|
||||||
"sample Build the sample project as a zip file.\n"
|
"sample Build the sample project as a zip file.\n"
|
||||||
"launcher Install launcher icons for freedesktop systems.\n"
|
"xdg-install Install launcher and icons for freedesktop systems.\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
if "help" in sys.argv:
|
if "help" in sys.argv:
|
||||||
@@ -312,15 +311,20 @@ if __name__ == "__main__":
|
|||||||
sys.argv.remove("sample")
|
sys.argv.remove("sample")
|
||||||
buildSampleZip()
|
buildSampleZip()
|
||||||
|
|
||||||
if "launcher" in sys.argv:
|
if "xdg-install" in sys.argv:
|
||||||
sys.argv.remove("launcher")
|
sys.argv.remove("xdg-install")
|
||||||
makeLauncherLinux()
|
if not sys.platform.startswith("win32"):
|
||||||
|
xdgInstall()
|
||||||
|
else:
|
||||||
|
print("ERROR: xdg-install cannot be used on Windows")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if len(sys.argv) <= 1:
|
if len(sys.argv) <= 1:
|
||||||
# Nothing more to do
|
# Nothing more to do
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Run the standard setup
|
# Run the standard setup
|
||||||
|
import setuptools # noqa: F401
|
||||||
setuptools.setup()
|
setuptools.setup()
|
||||||
|
|
||||||
# END Main
|
# END Main
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ The `setup.py` is a standard Python setup script with a couple of additional opt
|
|||||||
* `sample`: Will create a `sample.zip` file in the `nw/assets` folder.
|
* `sample`: Will create a `sample.zip` file in the `nw/assets` folder.
|
||||||
This is the file the New Project Wizard uses to generate an example project.
|
This is the file the New Project Wizard uses to generate an example project.
|
||||||
If novelWriter is run from source, this file is not needed.
|
If novelWriter is run from source, this file is not needed.
|
||||||
* `launcher`: Will try to copy the novelWriter icons and create a novelWriter.desktop file to launch
|
* `xdg-install`: Will install novelWriter icons, mimetype, and desktop and menu launcher on Linux desktops.
|
||||||
the application. This should work on standard Linux desktops.
|
the application. This should work on standard Linux desktops.
|
||||||
|
By default, this is installed for the current user. Run with `sudo` to install system-wide.
|
||||||
|
|
||||||
To install novelWriter as a local Python package, run:
|
To install novelWriter as a local Python package, run:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 683 B After Width: | Height: | Size: 683 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 985 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 986 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
@@ -2,7 +2,7 @@
|
|||||||
Type=Application
|
Type=Application
|
||||||
Encoding=UTF-8
|
Encoding=UTF-8
|
||||||
Name=novelWriter
|
Name=novelWriter
|
||||||
Comment=Multi-document markdown editor for novels
|
Comment=Multi-document markdown-like editor for novels
|
||||||
Exec=%%exec%% %f
|
Exec=%%exec%% %f
|
||||||
Icon=novelwriter
|
Icon=novelwriter
|
||||||
Categories=Qt;Office;WordProcessor;
|
Categories=Qt;Office;WordProcessor;
|
||||||
|
|||||||