From f9fc28d5ec5b911ac008abb2d7ef94f9c8294262 Mon Sep 17 00:00:00 2001 From: yedpodtrzitko Date: Wed, 1 May 2024 15:46:08 +0800 Subject: [PATCH 1/4] fix file opening on posix --- tagstudio/src/cli/ts_cli.py | 20 +++++----- tagstudio/src/qt/helpers/file_opener.py | 51 ++++++++++++++++--------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/tagstudio/src/cli/ts_cli.py b/tagstudio/src/cli/ts_cli.py index 30e14ae9..a26c5712 100644 --- a/tagstudio/src/cli/ts_cli.py +++ b/tagstudio/src/cli/ts_cli.py @@ -23,6 +23,7 @@ from src.core.ts_core import * from src.core.utils.web import * from src.core.utils.fs import * from src.core.library import * +from src.qt.helpers.file_opener import file_open WHITE_FG = '\033[37m' WHITE_BG = '\033[47m' @@ -352,8 +353,8 @@ class CliDriver: if not os.path.isfile(external_preview_path): temp = self.external_preview_default temp.save(external_preview_path) - if os.path.isfile(external_preview_path): - os.startfile(external_preview_path) + + file_open(external_preview_path) def set_external_preview_default(self) -> None: """Sets the external preview to its default image.""" @@ -1706,8 +1707,7 @@ class CliDriver: args = ['explorer', '/select,', filename] subprocess.call(args) else: - if os.path.isfile(filename): - os.startfile(filename) + file_open(filename) # refresh=False # self.scr_browse_entries_gallery(index) # Add Field ============================================================ @@ -2152,9 +2152,8 @@ class CliDriver: # Open ============================================================= elif (com[0].lower() == 'open' or com[0].lower() == 'o'): for match in self.lib.missing_matches[filename]: - fn = f'{os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry.filename)}' - if os.path.isfile(fn): - os.startfile(fn) + fn = os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry.filename) + file_open(fn) refresh = False # clear() # return self.scr_choose_missing_match(index, clear_scr=False) @@ -2276,8 +2275,8 @@ class CliDriver: # fn = f'{os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry_1.filename)}' # if os.path.isfile(fn): # os.startfile(fn) - os.startfile(dupe[0]) - os.startfile(dupe[1]) + file_open(dupe[0]) + file_open(dupe[1]) # clear() # return self.scr_resolve_dupe_files(index, clear_scr=False) # Mirror Entries =================================================== @@ -2385,8 +2384,7 @@ class CliDriver: # Open with Default Application ======================================== if (com[0].lower() == 'open' or com[0].lower() == 'o'): - if os.path.isfile(filename): - os.startfile(filename) + file_open(filename) # self.scr_edit_entry_tag_box(entry_index, field_index) # return # Close View =========================================================== diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index e6703f11..747144ca 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -5,6 +5,8 @@ import logging import os import subprocess +import sys +from os.path import isfile from PySide6.QtWidgets import QLabel @@ -15,7 +17,20 @@ INFO = f'[INFO]' logging.basicConfig(format="%(message)s", level=logging.INFO) -class FileOpenerHelper(): +def file_open(filepath: str, check_first: bool = True): + if check_first and not os.path.isfile(filepath): + logging.error(f'File not found: {filepath}') + return False + + if os.name == 'nt': + os.startfile(filepath) + elif sys.platform == 'darwin': + subprocess.Popen(['open', filepath]) + else: + subprocess.call(["xdg-open", filepath]) + + +class FileOpenerHelper: def __init__(self, filepath:str): self.filepath = filepath @@ -23,26 +38,26 @@ 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}') + logging.info(f'Opening file: {self.filepath}') + file_open(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: + if not os.path.exists(self.filepath): logging.error(f'File not found: {self.filepath}') + return + + logging.info(f'Opening file: {self.filepath}') + if os.name == 'nt': # Windows + command = f'explorer /select,"{self.filepath}"' + subprocess.run(command, shell=True) + elif sys.platform == 'darwin': + subprocess.Popen(['open', '-R', self.filepath]) + 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) class FileOpenerLabel(QLabel): From f40be005f89959f53ea5a379ff757ffc7ff2559a Mon Sep 17 00:00:00 2001 From: yedpodtrzitko Date: Wed, 1 May 2024 15:46:08 +0800 Subject: [PATCH 2/4] fix file opening on posix --- tagstudio/src/cli/ts_cli.py | 20 +++++----- tagstudio/src/qt/helpers/file_opener.py | 50 ++++++++++++++++--------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/tagstudio/src/cli/ts_cli.py b/tagstudio/src/cli/ts_cli.py index 30e14ae9..a26c5712 100644 --- a/tagstudio/src/cli/ts_cli.py +++ b/tagstudio/src/cli/ts_cli.py @@ -23,6 +23,7 @@ from src.core.ts_core import * from src.core.utils.web import * from src.core.utils.fs import * from src.core.library import * +from src.qt.helpers.file_opener import file_open WHITE_FG = '\033[37m' WHITE_BG = '\033[47m' @@ -352,8 +353,8 @@ class CliDriver: if not os.path.isfile(external_preview_path): temp = self.external_preview_default temp.save(external_preview_path) - if os.path.isfile(external_preview_path): - os.startfile(external_preview_path) + + file_open(external_preview_path) def set_external_preview_default(self) -> None: """Sets the external preview to its default image.""" @@ -1706,8 +1707,7 @@ class CliDriver: args = ['explorer', '/select,', filename] subprocess.call(args) else: - if os.path.isfile(filename): - os.startfile(filename) + file_open(filename) # refresh=False # self.scr_browse_entries_gallery(index) # Add Field ============================================================ @@ -2152,9 +2152,8 @@ class CliDriver: # Open ============================================================= elif (com[0].lower() == 'open' or com[0].lower() == 'o'): for match in self.lib.missing_matches[filename]: - fn = f'{os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry.filename)}' - if os.path.isfile(fn): - os.startfile(fn) + fn = os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry.filename) + file_open(fn) refresh = False # clear() # return self.scr_choose_missing_match(index, clear_scr=False) @@ -2276,8 +2275,8 @@ class CliDriver: # fn = f'{os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry_1.filename)}' # if os.path.isfile(fn): # os.startfile(fn) - os.startfile(dupe[0]) - os.startfile(dupe[1]) + file_open(dupe[0]) + file_open(dupe[1]) # clear() # return self.scr_resolve_dupe_files(index, clear_scr=False) # Mirror Entries =================================================== @@ -2385,8 +2384,7 @@ class CliDriver: # Open with Default Application ======================================== if (com[0].lower() == 'open' or com[0].lower() == 'o'): - if os.path.isfile(filename): - os.startfile(filename) + file_open(filename) # self.scr_edit_entry_tag_box(entry_index, field_index) # return # Close View =========================================================== diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index e6703f11..e91a1249 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -5,6 +5,7 @@ import logging import os import subprocess +import sys from PySide6.QtWidgets import QLabel @@ -15,7 +16,20 @@ INFO = f'[INFO]' logging.basicConfig(format="%(message)s", level=logging.INFO) -class FileOpenerHelper(): +def file_open(filepath: str, check_first: bool = True): + if check_first and not os.path.isfile(filepath): + logging.error(f'File not found: {filepath}') + return False + + if os.name == 'nt': + os.startfile(filepath) + elif sys.platform == 'darwin': + subprocess.Popen(['open', filepath]) + else: + subprocess.call(["xdg-open", filepath]) + + +class FileOpenerHelper: def __init__(self, filepath:str): self.filepath = filepath @@ -23,26 +37,26 @@ 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}') + logging.info(f'Opening file: {self.filepath}') + file_open(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: + if not os.path.exists(self.filepath): logging.error(f'File not found: {self.filepath}') + return + + logging.info(f'Opening file: {self.filepath}') + if os.name == 'nt': # Windows + command = f'explorer /select,"{self.filepath}"' + subprocess.run(command, shell=True) + elif sys.platform == 'darwin': + subprocess.Popen(['open', '-R', self.filepath]) + else: # 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) class FileOpenerLabel(QLabel): From c58590a22153f6ebab8fa21ba5eca3568f6ff77e Mon Sep 17 00:00:00 2001 From: Xarvex Date: Wed, 1 May 2024 03:26:36 -0500 Subject: [PATCH 3/4] Make use of open_file from #84 Refactor done in #80 essentially reverted changes Re-fixes #81, also re-fixes windows opening behind TagStudio --- tagstudio/src/cli/ts_cli.py | 5 +- tagstudio/src/qt/helpers/__init__.py | 5 +- tagstudio/src/qt/helpers/file_opener.py | 74 +++++++++++++++---------- tagstudio/src/qt/helpers/open_file.py | 49 ---------------- 4 files changed, 48 insertions(+), 85 deletions(-) delete mode 100644 tagstudio/src/qt/helpers/open_file.py diff --git a/tagstudio/src/cli/ts_cli.py b/tagstudio/src/cli/ts_cli.py index a26c5712..7ce1199d 100644 --- a/tagstudio/src/cli/ts_cli.py +++ b/tagstudio/src/cli/ts_cli.py @@ -23,7 +23,7 @@ from src.core.ts_core import * from src.core.utils.web import * from src.core.utils.fs import * from src.core.library import * -from src.qt.helpers.file_opener import file_open +from src.qt.helpers.file_opener import open_file WHITE_FG = '\033[37m' WHITE_BG = '\033[47m' @@ -2273,8 +2273,7 @@ class CliDriver: elif (com[0].lower() == 'open' or com[0].lower() == 'o'): # for match in self.lib.missing_matches[filename]: # fn = f'{os.path.normpath(self.lib.library_dir + "/" + match + "/" + entry_1.filename)}' - # if os.path.isfile(fn): - # os.startfile(fn) + # open_file(fn) file_open(dupe[0]) file_open(dupe[1]) # clear() diff --git a/tagstudio/src/qt/helpers/__init__.py b/tagstudio/src/qt/helpers/__init__.py index f66a6473..a79b66ab 100644 --- a/tagstudio/src/qt/helpers/__init__.py +++ b/tagstudio/src/qt/helpers/__init__.py @@ -1,4 +1,3 @@ -from .open_file import open_file -from .file_opener import FileOpenerHelper, FileOpenerLabel +from .file_opener import open_file, FileOpenerHelper, FileOpenerLabel from .function_iterator import FunctionIterator -from .custom_runnable import CustomRunnable \ No newline at end of file +from .custom_runnable import CustomRunnable diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index 747144ca..25f5d1dd 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -5,8 +5,9 @@ import logging import os import subprocess +import shutil import sys -from os.path import isfile +import traceback from PySide6.QtWidgets import QLabel @@ -17,17 +18,46 @@ INFO = f'[INFO]' logging.basicConfig(format="%(message)s", level=logging.INFO) -def file_open(filepath: str, check_first: bool = True): - if check_first and not os.path.isfile(filepath): - logging.error(f'File not found: {filepath}') - return False - - if os.name == 'nt': - os.startfile(filepath) - elif sys.platform == 'darwin': - subprocess.Popen(['open', filepath]) - else: - subprocess.call(["xdg-open", filepath]) +def open_file(path: str, file_manager: bool = False): + logging.info(f'Opening file: {path}') + if not os.path.exists(path): + logging.error(f'File not found: {path}') + return + try: + if sys.platform == "win32": + 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.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_BREAKAWAY_FROM_JOB) + else: + if sys.platform == "darwin": + command_name = "open" + command_args = [path] + if file_manager: + # will reveal in Finder + command_args.append("-R") + else: + 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] + command_args, close_fds=True) + else: + logging.info(f"Could not find {command_name} on system PATH") + except: + traceback.print_exc() class FileOpenerHelper: @@ -38,26 +68,10 @@ class FileOpenerHelper: self.filepath = filepath def open_file(self): - logging.info(f'Opening file: {self.filepath}') - file_open(self.filepath) + open_file(self.filepath) def open_explorer(self): - if not os.path.exists(self.filepath): - logging.error(f'File not found: {self.filepath}') - return - - logging.info(f'Opening file: {self.filepath}') - if os.name == 'nt': # Windows - command = f'explorer /select,"{self.filepath}"' - subprocess.run(command, shell=True) - elif sys.platform == 'darwin': - subprocess.Popen(['open', '-R', self.filepath]) - 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) + open_file(self.filepath, True) class FileOpenerLabel(QLabel): diff --git a/tagstudio/src/qt/helpers/open_file.py b/tagstudio/src/qt/helpers/open_file.py deleted file mode 100644 index f2e070e4..00000000 --- a/tagstudio/src/qt/helpers/open_file.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2024 Travis Abendshien (CyanVoxel). -# Licensed under the GPL-3.0 License. -# Created for TagStudio: https://github.com/CyanVoxel/TagStudio - - -import logging -import os -import sys -import traceback -import shutil -import subprocess - - -def open_file(path: str, file_manager: bool = False): - try: - if sys.platform == "win32": - 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.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_BREAKAWAY_FROM_JOB) - else: - if sys.platform == "darwin": - command_name = "open" - command_args = [path] - if file_manager: - # will reveal in Finder - command_args.append("-R") - else: - 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] + command_args, close_fds=True) - else: - logging.info(f"Could not find {command_name} on system PATH") - except: - traceback.print_exc() \ No newline at end of file From 81e0e7b072e4c132e3065602a0e02a59ce7ae2ab Mon Sep 17 00:00:00 2001 From: Xarvex Date: Wed, 1 May 2024 03:50:27 -0500 Subject: [PATCH 4/4] Accidental double sys import during merge conflict --- tagstudio/src/qt/helpers/file_opener.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tagstudio/src/qt/helpers/file_opener.py b/tagstudio/src/qt/helpers/file_opener.py index d2e2ffc6..25f5d1dd 100644 --- a/tagstudio/src/qt/helpers/file_opener.py +++ b/tagstudio/src/qt/helpers/file_opener.py @@ -8,7 +8,6 @@ import subprocess import shutil import sys import traceback -import sys from PySide6.QtWidgets import QLabel