From 7fafb06db02f119686d146fcc541d8fee6ee93a1 Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Wed, 12 Jun 2024 19:14:36 -0400 Subject: [PATCH 1/6] Added the option to delete files in the right click context menu --- tagstudio/src/qt/helpers/file_deleter.py | 39 ++++++++++++++++++++++++ tagstudio/src/qt/widgets/item_thumb.py | 15 ++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tagstudio/src/qt/helpers/file_deleter.py diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py new file mode 100644 index 000000000..23000815c --- /dev/null +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -0,0 +1,39 @@ +import logging +import os.path +import subprocess +import sys +import traceback +from pathlib import Path +from typing import Callable + +ERROR = f"[ERROR]" +WARNING = f"[WARNING]" +INFO = f"[INFO]" + +logging.basicConfig(format="%(message)s", level=logging.INFO) + +def delete_file(path: str | Path, callback: Callable): + _path = str(path) + logging.info(f"Deleting file: {_path}") + if not os.path.exists(_path): + logging.error(f"File not found: {_path}") + return + try: + os.remove(path) + callback() + except: + traceback.print_exc() + +class FileDeleterHelper: + + def __init__(self, filepath: str | Path): + self.filepath = str(filepath) + + def set_filepath(self, filepath: str | Path): + self.filepath = str(filepath) + + def set_delete_callback(self, callback: Callable): + self.delete_callback = callback + + def delete_file(self): + delete_file(self.filepath, self.delete_callback) \ No newline at end of file diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index 8cd238749..28334d786 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -12,7 +12,7 @@ from typing import Optional from PIL import Image, ImageQt -from PySide6.QtCore import Qt, QSize, QEvent +from PySide6.QtCore import Qt, QSize, QEvent, QThreadPool from PySide6.QtGui import QPixmap, QEnterEvent, QAction from PySide6.QtWidgets import ( QWidget, @@ -28,6 +28,7 @@ from src.core.constants import AUDIO_TYPES, VIDEO_TYPES, IMAGE_TYPES from src.qt.flowlayout import FlowWidget from src.qt.helpers.file_opener import FileOpenerHelper +from src.qt.helpers.file_deleter import FileDeleterHelper from src.qt.widgets.thumb_renderer import ThumbRenderer from src.qt.widgets.thumb_button import ThumbButton @@ -191,12 +192,16 @@ def __init__( self.thumb_button.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu) self.opener = FileOpenerHelper("") + self.deleter = FileDeleterHelper("") 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.triggered.connect(self.opener.open_explorer) + delete_action = QAction("Delete", self) + delete_action.triggered.connect(self.deleter.delete_file) self.thumb_button.addAction(open_file_action) self.thumb_button.addAction(open_explorer_action) + self.thumb_button.addAction(delete_action) # Static Badges ======================================================== @@ -414,6 +419,8 @@ def set_item_id(self, id: int): entry = self.lib.get_entry(self.item_id) filepath = self.lib.library_dir / entry.path / entry.filename self.opener.set_filepath(filepath) + self.deleter.set_filepath(filepath) + self.deleter.set_delete_callback(self._on_delete) def assign_favorite(self, value: bool): # Switching mode to None to bypass mode-specific operations when the @@ -491,3 +498,9 @@ def toggle_tag(entry: Entry): if self.panel.isOpen: self.panel.update_widgets() self.panel.driver.update_badges() + + def _on_delete(self): + entry = self.lib.get_entry(self.item_id) + self.lib.remove_entry(self.item_id) + self.panel.driver.purge_item_from_navigation(entry.type, self.item_id) + self.panel.driver.filter_items() \ No newline at end of file From b6b66ae3113fbaaba0b9faf765644ac7bcf16e48 Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Wed, 12 Jun 2024 19:21:42 -0400 Subject: [PATCH 2/6] Reformatted with Ruff --- tagstudio/src/qt/helpers/file_deleter.py | 5 +++-- tagstudio/src/qt/widgets/item_thumb.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py index 23000815c..6c1de715c 100644 --- a/tagstudio/src/qt/helpers/file_deleter.py +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -12,6 +12,7 @@ logging.basicConfig(format="%(message)s", level=logging.INFO) + def delete_file(path: str | Path, callback: Callable): _path = str(path) logging.info(f"Deleting file: {_path}") @@ -24,8 +25,8 @@ def delete_file(path: str | Path, callback: Callable): except: traceback.print_exc() -class FileDeleterHelper: +class FileDeleterHelper: def __init__(self, filepath: str | Path): self.filepath = str(filepath) @@ -36,4 +37,4 @@ def set_delete_callback(self, callback: Callable): self.delete_callback = callback def delete_file(self): - delete_file(self.filepath, self.delete_callback) \ No newline at end of file + delete_file(self.filepath, self.delete_callback) diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index 28334d786..0dd02d1f4 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -503,4 +503,4 @@ def _on_delete(self): entry = self.lib.get_entry(self.item_id) self.lib.remove_entry(self.item_id) self.panel.driver.purge_item_from_navigation(entry.type, self.item_id) - self.panel.driver.filter_items() \ No newline at end of file + self.panel.driver.filter_items() From 531554c0ab33205e1210eff2023472cecebf323c Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Wed, 12 Jun 2024 19:27:54 -0400 Subject: [PATCH 3/6] Removed unused import --- tagstudio/src/qt/widgets/item_thumb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index 0dd02d1f4..f039e4a19 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -12,7 +12,7 @@ from typing import Optional from PIL import Image, ImageQt -from PySide6.QtCore import Qt, QSize, QEvent, QThreadPool +from PySide6.QtCore import Qt, QSize, QEvent from PySide6.QtGui import QPixmap, QEnterEvent, QAction from PySide6.QtWidgets import ( QWidget, From eb182302895e554c902c4eeeaef3c6afd0c8dc9e Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Thu, 13 Jun 2024 08:59:16 -0400 Subject: [PATCH 4/6] Updated to use pathlib instead of os --- tagstudio/src/qt/helpers/file_deleter.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py index 6c1de715c..104b77465 100644 --- a/tagstudio/src/qt/helpers/file_deleter.py +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -1,5 +1,5 @@ import logging -import os.path +import pathlib import subprocess import sys import traceback @@ -15,12 +15,13 @@ def delete_file(path: str | Path, callback: Callable): _path = str(path) + _file = Path(_path) logging.info(f"Deleting file: {_path}") - if not os.path.exists(_path): + if not _file.exists(): logging.error(f"File not found: {_path}") return try: - os.remove(path) + _file.unlink() callback() except: traceback.print_exc() From a1a695cfb911632d54669301cf78528bbbc6b7a9 Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Thu, 13 Jun 2024 11:47:24 -0400 Subject: [PATCH 5/6] - removed unused imports - swapped out `typing` to `collections.abc` - removed unnecessary `str()` conversion in `FileDeleterHelper` constructor and `set_filepath` --- tagstudio/src/qt/helpers/file_deleter.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py index 104b77465..d8a36e346 100644 --- a/tagstudio/src/qt/helpers/file_deleter.py +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -1,10 +1,7 @@ import logging -import pathlib -import subprocess -import sys import traceback from pathlib import Path -from typing import Callable +from collections.abc import Callable ERROR = f"[ERROR]" WARNING = f"[WARNING]" @@ -12,7 +9,6 @@ logging.basicConfig(format="%(message)s", level=logging.INFO) - def delete_file(path: str | Path, callback: Callable): _path = str(path) _file = Path(_path) @@ -29,10 +25,10 @@ def delete_file(path: str | Path, callback: Callable): class FileDeleterHelper: def __init__(self, filepath: str | Path): - self.filepath = str(filepath) + self.filepath = filepath def set_filepath(self, filepath: str | Path): - self.filepath = str(filepath) + self.filepath = filepath def set_delete_callback(self, callback: Callable): self.delete_callback = callback From d8672387833b16512525c2c9f2a2de86f0c6c773 Mon Sep 17 00:00:00 2001 From: peterbousaada Date: Thu, 13 Jun 2024 11:56:22 -0400 Subject: [PATCH 6/6] Swapped stacktrace to logging.exception in `file_deleter.py` --- tagstudio/src/qt/helpers/file_deleter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py index d8a36e346..3e99b6963 100644 --- a/tagstudio/src/qt/helpers/file_deleter.py +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -9,6 +9,7 @@ logging.basicConfig(format="%(message)s", level=logging.INFO) + def delete_file(path: str | Path, callback: Callable): _path = str(path) _file = Path(_path) @@ -19,8 +20,8 @@ def delete_file(path: str | Path, callback: Callable): try: _file.unlink() callback() - except: - traceback.print_exc() + except Exception as exception: + logging.exception(exception) class FileDeleterHelper: