diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 8a0fe19311..799846df72 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -38,6 +38,7 @@ from blenderbim.bim.ui import IFCFileSelector from blenderbim.bim.helper import get_enum_items from mathutils import Vector, Matrix, Euler from math import radians +from pathlib import Path class SetTab(bpy.types.Operator): @@ -127,7 +128,7 @@ class SelectIfcFile(bpy.types.Operator, IFCFileSelector): bl_idname = "bim.select_ifc_file" bl_label = "Select IFC File" bl_options = {"REGISTER", "UNDO"} - bl_description = "Select a different IFC file" + bl_description = f"Select a different IFC file.\n{tool.Blender.operator_invoke_filepath_hotkeys_description}" filepath: bpy.props.StringProperty(subtype="FILE_PATH") filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=False) @@ -138,6 +139,11 @@ class SelectIfcFile(bpy.types.Operator, IFCFileSelector): return {"FINISHED"} def invoke(self, context, event): + filepath = Path(context.scene.BIMProperties.ifc_file) + res = tool.Blender.operator_invoke_filepath_hotkeys(self, context, event, filepath) + if res is not None: + return res + context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index 20aebd3019..f69513d12d 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -551,6 +551,50 @@ class Blender(blenderbim.core.tool.Blender): for axis_idx in range(3): attr[axis_idx] = lock_state + operator_invoke_filepath_hotkeys_description = "Hold Shift to open the file, Alt to browse containing directory" + + @classmethod + def operator_invoke_filepath_hotkeys(cls, operator, context, event, filepath: Path): + if not event.alt and not event.shift: + return + + import platform + import os + import subprocess + + def open_file_or_folder(path): + if platform.system() == "Windows": + os.startfile(path) + elif platform.system() == "Darwin": + subprocess.Popen(["open", path]) + else: + subprocess.Popen(["xdg-open", path]) + + # resolve relative filepaths with .blend path by default + if not filepath.is_absolute(): + if bpy.data.filepath: + filepath = Path(bpy.data.filepath).parent / filepath + else: + operator.report({"ERROR"}, f'Couldn\'t resolve relative filepath "{filepath.as_posix()}"') + return {"CANCELLED"} + + # holding ALT - open file directory + if event.alt == True: + # open directory + filepath = filepath.parent + if not filepath.exists(): + operator.report({"ERROR"}, f'Cannot open non-existing directory: "{filepath.as_posix()}"') + return {"CANCELLED"} + open_file_or_folder(filepath.as_posix()) + return {"PASS_THROUGH"} + + # holding sHIFT - open file + if not filepath.exists(): + operator.report({"ERROR"}, f'Cannot open non-existing file: "{filepath.as_posix()}"') + return {"CANCELLED"} + open_file_or_folder(filepath.as_posix()) + return {"PASS_THROUGH"} + class Modifier: @classmethod def is_eligible_for_railing_modifier(cls, obj):