From d7a74dd6a42e5975dfe82617623a553e72fd2086 Mon Sep 17 00:00:00 2001 From: Bruno Postle Date: Sun, 7 May 2023 13:08:28 +0100 Subject: [PATCH] BlenderBIM ifc file association (linux only) #2399 --- src/blenderbim/Makefile | 3 + src/blenderbim/blenderbim/bim/__init__.py | 2 + src/blenderbim/blenderbim/bim/operator.py | 123 ++++++++++++++++++ src/blenderbim/blenderbim/bim/ui.py | 3 + .../{ => blenderbim/libs}/desktop/Makefile | 0 .../{ => blenderbim/libs}/desktop/README.md | 0 .../{ => blenderbim/libs}/desktop/blenderbim | 0 .../libs}/desktop/blenderbim.desktop | 0 .../libs}/desktop/blenderbim.png | Bin .../libs}/desktop/blenderbim.xml | 0 .../libs}/desktop/x-ifc_128x128.png | Bin .../libs}/desktop/x-ifc_512x512.png | Bin 12 files changed, 131 insertions(+) rename src/blenderbim/{ => blenderbim/libs}/desktop/Makefile (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/README.md (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/blenderbim (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/blenderbim.desktop (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/blenderbim.png (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/blenderbim.xml (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/x-ifc_128x128.png (100%) rename src/blenderbim/{ => blenderbim/libs}/desktop/x-ifc_512x512.png (100%) diff --git a/src/blenderbim/Makefile b/src/blenderbim/Makefile index a9a853f5c8..00fc51ee32 100644 --- a/src/blenderbim/Makefile +++ b/src/blenderbim/Makefile @@ -664,6 +664,9 @@ endif cp -r dist/working/bpypolyskel-master/bpypolyskel dist/blenderbim/libs/site/packages/ rm -rf dist/working + # Required for Desktop icon and file association + cp -r blenderbim/libs/desktop dist/blenderbim/libs/ + # Remove dependencies also bundled with Blender rm -rf dist/blenderbim/libs/site/packages/numpy rm -rf dist/blenderbim/libs/site/packages/numpy.libs diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index 9b8e5bc70a..b3e9279a67 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -95,6 +95,8 @@ classes = [ operator.SelectIfcFile, operator.ReloadSelectedIfcFile, operator.SelectSchemaDir, + operator.FileAssociate, + operator.FileUnassociate, operator.SelectURIAttribute, operator.EditBlenderCollection, operator.BIM_OT_open_webbrowser, diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 8a0fd0bc21..f81124a7be 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -22,6 +22,9 @@ import json import time import logging import textwrap +import shutil +import platform +import subprocess import tempfile import webbrowser import ifcopenshell @@ -148,6 +151,126 @@ class SelectSchemaDir(bpy.types.Operator): return {"RUNNING_MODAL"} +class FileAssociate(bpy.types.Operator): + bl_idname = "bim.file_associate" + bl_label = "Associate BlenderBIM with *.ifc files" + bl_options = {"REGISTER", "UNDO"} + bl_description = "Creates a Desktop launcher and associates it with IFC files" + + @classmethod + def poll(cls, context): + if platform.system() == "Linux": + return True + # TODO Windows and Darwin + # https://stackoverflow.com/questions/1082889/how-to-change-filetype-association-in-the-registry + return False + + def execute(self, context): + src_dir = os.path.join(os.path.dirname(__file__), "../libs/desktop") + binary_path = bpy.app.binary_path + if platform.system() == "Linux": + destdir = os.path.join(os.environ["HOME"], ".local") + self.install_desktop_linux(src_dir=src_dir, destdir=destdir, binary_path=binary_path) + return {"FINISHED"} + + def install_desktop_linux(self, src_dir=None, destdir="/tmp", binary_path="/usr/bin/blender"): + """Creates linux file assocations and launcher icon""" + + for rel_path in ( + "bin", + "share/icons/hicolor/128x128/apps", + "share/icons/hicolor/128x128/mimetypes", + "share/applications", + "share/mime/packages", + ): + os.makedirs(os.path.join(destdir, rel_path), exist_ok=True) + + shutil.copy( + os.path.join(src_dir, "blenderbim.png"), + os.path.join(destdir, "share/icons/hicolor/128x128/apps"), + ) + shutil.copy( + os.path.join(src_dir, "blenderbim.desktop"), + os.path.join(destdir, "share/applications"), + ) + shutil.copy( + os.path.join(src_dir, "blenderbim.xml"), + os.path.join(destdir, "share/mime/packages"), + ) + shutil.copyfile( + os.path.join(src_dir, "x-ifc_128x128.png"), + os.path.join(destdir, "share/icons/hicolor/128x128/mimetypes", "x-ifc.png"), + ) + + # copy and rewrite wrapper script + with open(os.path.join(src_dir, "blenderbim"), "r") as wrapper_template: + filedata = wrapper_template.read() + filedata = filedata.replace("#BLENDER_EXE=/opt/blender-3.3/blender", 'BLENDER_EXE="' + binary_path + '"') + with open(os.path.join(destdir, "bin", "blenderbim"), "w") as wrapper: + wrapper.write(filedata) + + os.chmod(os.path.join(destdir, "bin", "blenderbim"), 0o755) + + self.refresh_system_linux(destdir=destdir) + + def refresh_system_linux(self, destdir="/tmp"): + """Attempt to update mime and desktop databases""" + try: + subprocess.call(["update-mime-database", os.path.join(destdir, "share/mime")]) + except: + pass + try: + subprocess.call(["update-desktop-database", os.path.join(destdir, "share/applications")]) + except: + pass + + +class FileUnassociate(bpy.types.Operator): + bl_idname = "bim.file_unassociate" + bl_label = "Remove BlenderBIM *.ifc association" + bl_options = {"REGISTER", "UNDO"} + bl_description = "Removes Desktop launcher and unassociates it with IFC files" + + @classmethod + def poll(cls, context): + if platform.system() == "Linux": + return True + return False + + def execute(self, context): + if platform.system() == "Linux": + destdir = os.path.join(os.environ["HOME"], ".local") + self.uninstall_desktop_linux(destdir=destdir) + return {"FINISHED"} + + def uninstall_desktop_linux(self, destdir="/tmp"): + """Removes linux file assocations and launcher icon""" + for rel_path in ( + "share/icons/hicolor/128x128/apps/blenderbim.png", + "share/icons/hicolor/128x128/mimetypes/x-ifc.png", + "share/applications/blenderbim.desktop", + "share/mime/packages/blenderbim.xml", + "bin/blenderbim", + ): + try: + os.remove(os.path.join(destdir, rel_path)) + except: + pass + + self.refresh_system_linux(destdir=destdir) + + def refresh_system_linux(self, destdir="/tmp"): + """Attempt to update mime and desktop databases""" + try: + subprocess.call(["update-mime-database", os.path.join(destdir, "share/mime")]) + except: + pass + try: + subprocess.call(["update-desktop-database", os.path.join(destdir, "share/applications")]) + except: + pass + + class OpenUpstream(bpy.types.Operator): bl_idname = "bim.open_upstream" bl_label = "Open Upstream Reference" diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index c9e691eed6..3a642ed839 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -175,6 +175,9 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row.operator("bim.open_upstream", text="Visit Wiki").page = "wiki" row.operator("bim.open_upstream", text="Visit Community").page = "community" row = layout.row() + row.operator("bim.file_associate", icon="LOCKVIEW_ON") + row.operator("bim.file_unassociate", icon="LOCKVIEW_OFF") + row = layout.row() row.prop(self, "svg2pdf_command") row = layout.row() row.prop(self, "svg2dxf_command") diff --git a/src/blenderbim/desktop/Makefile b/src/blenderbim/blenderbim/libs/desktop/Makefile similarity index 100% rename from src/blenderbim/desktop/Makefile rename to src/blenderbim/blenderbim/libs/desktop/Makefile diff --git a/src/blenderbim/desktop/README.md b/src/blenderbim/blenderbim/libs/desktop/README.md similarity index 100% rename from src/blenderbim/desktop/README.md rename to src/blenderbim/blenderbim/libs/desktop/README.md diff --git a/src/blenderbim/desktop/blenderbim b/src/blenderbim/blenderbim/libs/desktop/blenderbim similarity index 100% rename from src/blenderbim/desktop/blenderbim rename to src/blenderbim/blenderbim/libs/desktop/blenderbim diff --git a/src/blenderbim/desktop/blenderbim.desktop b/src/blenderbim/blenderbim/libs/desktop/blenderbim.desktop similarity index 100% rename from src/blenderbim/desktop/blenderbim.desktop rename to src/blenderbim/blenderbim/libs/desktop/blenderbim.desktop diff --git a/src/blenderbim/desktop/blenderbim.png b/src/blenderbim/blenderbim/libs/desktop/blenderbim.png similarity index 100% rename from src/blenderbim/desktop/blenderbim.png rename to src/blenderbim/blenderbim/libs/desktop/blenderbim.png diff --git a/src/blenderbim/desktop/blenderbim.xml b/src/blenderbim/blenderbim/libs/desktop/blenderbim.xml similarity index 100% rename from src/blenderbim/desktop/blenderbim.xml rename to src/blenderbim/blenderbim/libs/desktop/blenderbim.xml diff --git a/src/blenderbim/desktop/x-ifc_128x128.png b/src/blenderbim/blenderbim/libs/desktop/x-ifc_128x128.png similarity index 100% rename from src/blenderbim/desktop/x-ifc_128x128.png rename to src/blenderbim/blenderbim/libs/desktop/x-ifc_128x128.png diff --git a/src/blenderbim/desktop/x-ifc_512x512.png b/src/blenderbim/blenderbim/libs/desktop/x-ifc_512x512.png similarity index 100% rename from src/blenderbim/desktop/x-ifc_512x512.png rename to src/blenderbim/blenderbim/libs/desktop/x-ifc_512x512.png