diff --git a/.gitignore b/.gitignore index 830a409a..66c21d61 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.spec *.egg-info setup.iss +novelwriter.desktop # Documentation /docs/build/ diff --git a/README.md b/README.md index 9efa0b24..54348b1f 100644 --- a/README.md +++ b/README.md @@ -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: ```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). diff --git a/setup.py b/setup.py index c3c5710b..1eae8bf7 100755 --- a/setup.py +++ b/setup.py @@ -21,7 +21,6 @@ import os import sys import shutil import subprocess -import setuptools # =============================================================================================== # # Qt Assistant Documentation Builder @@ -140,14 +139,17 @@ def buildSampleZip(): # Create Launcher # =============================================================================================== # -def makeLauncherLinux(): +def xdgInstall(): """Will attempt to install icons and make a launcher. """ print("") - print("Creating Launcher") - print("=================") + print("XDG Install") + print("===========") print("") + # Find Executable(s) + # ================== + exOpts = [] testExec = shutil.which("novelWriter") @@ -185,95 +187,92 @@ def makeLauncherLinux(): sys.exit(1) print("Using executable: %s " % useExec) + print("") + + # Create and Install Launcher + # =========================== - # Read the Template 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 = desktopData.replace(r"%%exec%%", useExec) + with open("./novelwriter.desktop", mode="w+") as outFile: + outFile.write(desktopData) - desktopFile = "/usr/share/applications/novelwriter.desktop" - try: - with open(desktopFile, mode="w+") as outFile: - outFile.write(desktopData) - print("Wrote file: %s" % desktopFile) - except Exception as e: - print("Error: Could not write novelwriter.desktop file.") - print(str(e)) - sys.exit(1) + exCode = subprocess.call( + ["xdg-desktop-menu", "install", "--novendor", "./novelwriter.desktop"] + ) + if exCode == 0: + print("Installed menu desktop file") + else: + print(f"Error {exCode}: Could not install menu desktop file") + + 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("") - # Copy Icons + # Install MimeType + # ================ - iconDirs = [ - "/usr/share/icons/hicolor/24x24/apps", - "/usr/share/icons/hicolor/48x48/apps", - "/usr/share/icons/hicolor/96x96/apps", - "/usr/share/icons/hicolor/256x256/apps", - "/usr/share/icons/hicolor/512x512/apps", - "/usr/share/icons/hicolor/scalable/apps", - "/usr/share/icons/hicolor/scalable/mimetypes", - ] - 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)) + exCode = subprocess.call([ + "xdg-mime", "install", + "./setup/mime/x-novelwriter-project.xml" + ]) + if exCode == 0: + print("Installed mimetype") + else: + print(f"Error {exCode}: Could not install mimetype") print("") - # Update System - 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)) + # Install Icons + # ============= - try: - subprocess.call(["update-icon-caches", "/usr/share/icons/*"]) - print("Updated icon cache.") - except Exception as e: - print("Error: Filed to update icon cache.") - print(str(e)) + sizeArr = ["16", "22", "24", "32", "48", "64", "96", "128", "256", "512"] + + # App Icon + for aSize in sizeArr: + exCode = subprocess.call([ + "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("Done!") @@ -293,10 +292,10 @@ if __name__ == "__main__": "======================\n" "This tool provides some additional setup commands for novelWriter.\n" "\n" - "help Print the help message.\n" - "qthelp Build the help documentation for use with the QtAssistant.\n" - "sample Build the sample project as a zip file.\n" - "launcher Install launcher icons for freedesktop systems.\n" + "help Print the help message.\n" + "qthelp Build the help documentation for use with the QtAssistant.\n" + "sample Build the sample project as a zip file.\n" + "xdg-install Install launcher and icons for freedesktop systems.\n" ) if "help" in sys.argv: @@ -312,15 +311,20 @@ if __name__ == "__main__": sys.argv.remove("sample") buildSampleZip() - if "launcher" in sys.argv: - sys.argv.remove("launcher") - makeLauncherLinux() + if "xdg-install" in sys.argv: + sys.argv.remove("xdg-install") + 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: # Nothing more to do sys.exit(0) # Run the standard setup + import setuptools # noqa: F401 setuptools.setup() # END Main diff --git a/setup/README.md b/setup/README.md index 81479cf7..252f70cd 100644 --- a/setup/README.md +++ b/setup/README.md @@ -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. 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. -* `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. + 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: ```bash diff --git a/setup/icons/1024x1024/novelwriter.png b/setup/icons/scaled/icon-novelwriter-1024.png similarity index 100% rename from setup/icons/1024x1024/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-1024.png diff --git a/setup/icons/128x128/novelwriter.png b/setup/icons/scaled/icon-novelwriter-128.png similarity index 100% rename from setup/icons/128x128/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-128.png diff --git a/setup/icons/16x16/novelwriter.png b/setup/icons/scaled/icon-novelwriter-16.png similarity index 100% rename from setup/icons/16x16/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-16.png diff --git a/setup/icons/16x16@2x/novelwriter.png b/setup/icons/scaled/icon-novelwriter-16@2.png similarity index 100% rename from setup/icons/16x16@2x/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-16@2.png diff --git a/setup/icons/18x18@2x/novelwriter.png b/setup/icons/scaled/icon-novelwriter-18@2.png similarity index 100% rename from setup/icons/18x18@2x/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-18@2.png diff --git a/setup/icons/scaled/icon-novelwriter-22.png b/setup/icons/scaled/icon-novelwriter-22.png new file mode 100644 index 00000000..27ca5f32 Binary files /dev/null and b/setup/icons/scaled/icon-novelwriter-22.png differ diff --git a/setup/icons/24x24/novelwriter.png b/setup/icons/scaled/icon-novelwriter-24.png similarity index 100% rename from setup/icons/24x24/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-24.png diff --git a/setup/icons/256x256/novelwriter.png b/setup/icons/scaled/icon-novelwriter-256.png similarity index 100% rename from setup/icons/256x256/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-256.png diff --git a/setup/icons/32x32/novelwriter.png b/setup/icons/scaled/icon-novelwriter-32.png similarity index 100% rename from setup/icons/32x32/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-32.png diff --git a/setup/icons/48x48/novelwriter.png b/setup/icons/scaled/icon-novelwriter-48.png similarity index 100% rename from setup/icons/48x48/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-48.png diff --git a/setup/icons/512x512/novelwriter.png b/setup/icons/scaled/icon-novelwriter-512.png similarity index 100% rename from setup/icons/512x512/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-512.png diff --git a/setup/icons/32x32@2x/novelwriter.png b/setup/icons/scaled/icon-novelwriter-64.png similarity index 100% rename from setup/icons/32x32@2x/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-64.png diff --git a/setup/icons/96x96/novelwriter.png b/setup/icons/scaled/icon-novelwriter-96.png similarity index 100% rename from setup/icons/96x96/novelwriter.png rename to setup/icons/scaled/icon-novelwriter-96.png diff --git a/setup/icons/64x64/novelwriter.png b/setup/icons/scaled/icon-novelwriter32@2.png similarity index 100% rename from setup/icons/64x64/novelwriter.png rename to setup/icons/scaled/icon-novelwriter32@2.png diff --git a/setup/icons/1024x1024/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-1024.png similarity index 100% rename from setup/icons/1024x1024/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-1024.png diff --git a/setup/icons/128x128/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-128.png similarity index 100% rename from setup/icons/128x128/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-128.png diff --git a/setup/icons/16x16/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-16.png similarity index 100% rename from setup/icons/16x16/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-16.png diff --git a/setup/icons/16x16@2x/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-16@2.png similarity index 100% rename from setup/icons/16x16@2x/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-16@2.png diff --git a/setup/icons/18x18@2x/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-18@2.png similarity index 100% rename from setup/icons/18x18@2x/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-18@2.png diff --git a/setup/icons/scaled/mime-novelwriter-22.png b/setup/icons/scaled/mime-novelwriter-22.png new file mode 100644 index 00000000..384e2ca4 Binary files /dev/null and b/setup/icons/scaled/mime-novelwriter-22.png differ diff --git a/setup/icons/24x24/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-24.png similarity index 100% rename from setup/icons/24x24/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-24.png diff --git a/setup/icons/256x256/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-256.png similarity index 100% rename from setup/icons/256x256/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-256.png diff --git a/setup/icons/32x32/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-32.png similarity index 100% rename from setup/icons/32x32/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-32.png diff --git a/setup/icons/32x32@2x/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-32@2.png similarity index 100% rename from setup/icons/32x32@2x/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-32@2.png diff --git a/setup/icons/48x48/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-48.png similarity index 100% rename from setup/icons/48x48/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-48.png diff --git a/setup/icons/512x512/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-512.png similarity index 100% rename from setup/icons/512x512/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-512.png diff --git a/setup/icons/64x64/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-64.png similarity index 100% rename from setup/icons/64x64/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-64.png diff --git a/setup/icons/96x96/x-novelwriter-project.png b/setup/icons/scaled/mime-novelwriter-96.png similarity index 100% rename from setup/icons/96x96/x-novelwriter-project.png rename to setup/icons/scaled/mime-novelwriter-96.png diff --git a/setup/novelwriter.desktop b/setup/novelwriter.desktop index 69550600..37236fab 100644 --- a/setup/novelwriter.desktop +++ b/setup/novelwriter.desktop @@ -2,7 +2,7 @@ Type=Application Encoding=UTF-8 Name=novelWriter -Comment=Multi-document markdown editor for novels +Comment=Multi-document markdown-like editor for novels Exec=%%exec%% %f Icon=novelwriter Categories=Qt;Office;WordProcessor;