From 2d558efde7fcbd46c7b480329f3722ac12a629cc Mon Sep 17 00:00:00 2001 From: Xarvex Date: Sun, 28 Apr 2024 04:09:07 -0500 Subject: [PATCH] Allow opening and selecting files in file managers for all platforms Fixes: #81 Refactored file opener helper to use already present open_file Refactored open_file to allow option for file manager --- tagstudio/src/qt/ts_qt.py | 55 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 018a7da..d1cc846 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -65,20 +65,38 @@ logging.basicConfig(format="%(message)s", level=logging.INFO) QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, os.getcwd()) -def open_file(path: str): +def open_file(path: str, file_manager: bool = False): try: if sys.platform == "win32": - # Windows needs special attention to handle spaces in the file - # first parameter is for title, NOT filepath - subprocess.Popen(["start", "", os.path.normpath(path)], shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) + normpath = os.path.normpath(path) + if file_manager: + command_name = "explorer" + command_args = [f"/select,{normpath}"] + else: + command_name = "start" + # first parameter is for title, NOT filepath + command_args = ["", normpath] + subprocess.Popen([command_name] + command_args, shell=True, close_fds=True, creationflags=subprocess.DETACHED_PROCESS) else: if sys.platform == "darwin": command_name = "open" + command_args = [path] + if file_manager: + # will reveal in Finder + command_args = command_args.append("-R") else: - command_name = "xdg-open" + if file_manager: + command_name = "dbus-send" + # might not be guaranteed to launch default? + command_args = ["--session", "--dest=org.freedesktop.FileManager1", "--type=method_call", + "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1.ShowItems", + f"array:string:file://{path}", "string:"] + else: + command_name = "xdg-open" + command_args = [path] command = shutil.which(command_name) if command is not None: - subprocess.Popen([command, path], close_fds=True) + subprocess.Popen([command] + command_args, close_fds=True) else: logging.info(f"Could not find {command_name} on system PATH") except: @@ -2016,26 +2034,11 @@ class FileOpenerHelper(): self.filepath = filepath def open_file(self): - if os.path.exists(self.filepath): - os.startfile(self.filepath) - logging.info(f'Opening file: {self.filepath}') - else: - logging.error(f'File not found: {self.filepath}') + open_file(self.filepath) def open_explorer(self): - if os.path.exists(self.filepath): - logging.info(f'Opening file: {self.filepath}') - if os.name == 'nt': # Windows - command = f'explorer /select,"{self.filepath}"' - subprocess.run(command, shell=True) - else: # macOS and Linux - command = f'nautilus --select "{self.filepath}"' # Adjust for your Linux file manager if different - if subprocess.run(command, shell=True).returncode == 0: - file_loc = os.path.dirname(self.filepath) - file_loc = os.path.normpath(file_loc) - os.startfile(file_loc) - else: - logging.error(f'File not found: {self.filepath}') + open_file(self.filepath, True) + class FileOpenerLabel(QLabel): def __init__(self, text, parent=None): super().__init__(text, parent) @@ -2087,7 +2090,7 @@ class PreviewPanel(QWidget): self.preview_img.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper('') self.open_file_action = QAction('Open file', self) - self.open_explorer_action = QAction('Open file in explorer', self) + self.open_explorer_action = QAction('Open in file manager', self) self.preview_img.addAction(self.open_file_action) self.preview_img.addAction(self.open_explorer_action) @@ -2946,7 +2949,7 @@ class ItemThumb(FlowWidget): self.opener = FileOpenerHelper('') open_file_action = QAction('Open file', self) open_file_action.triggered.connect(self.opener.open_file) - open_explorer_action = QAction('Open file in explorer', self) + open_explorer_action = QAction('Open in file manager', self) open_explorer_action.triggered.connect(self.opener.open_explorer) self.thumb_button.addAction(open_file_action) self.thumb_button.addAction(open_explorer_action)