mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-01-28 22:01:24 +00:00
* feat: port file trashing (#409) to sql * translations: translate file deletion actions * fix: rename method from refactor conflict * refactor: implement feedback
This commit is contained in:
committed by
GitHub
parent
466af1e6a6
commit
a3df70bb8d
@@ -12,6 +12,7 @@ PySide6_Addons==6.8.0.1
|
||||
PySide6_Essentials==6.8.0.1
|
||||
PySide6==6.8.0.1
|
||||
rawpy==0.22.0
|
||||
Send2Trash==1.8.3
|
||||
SQLAlchemy==2.0.34
|
||||
structlog==24.4.0
|
||||
typing_extensions>=3.10.0.0,<=4.11.0
|
||||
|
||||
BIN
tagstudio/resources/qt/videos/placeholder.mp4
Normal file
BIN
tagstudio/resources/qt/videos/placeholder.mp4
Normal file
Binary file not shown.
@@ -157,6 +157,9 @@
|
||||
"macros.running.dialog.new_entries": "Running Configured Macros on {count}/{total} New File Entries...",
|
||||
"macros.running.dialog.title": "Running Macros on New Entries",
|
||||
"media_player.autoplay": "Autoplay",
|
||||
"menu.delete_selected_files_ambiguous": "Move File(s) to {trash_term}",
|
||||
"menu.delete_selected_files_plural": "Move Files to {trash_term}",
|
||||
"menu.delete_selected_files_singular": "Move File to {trash_term}",
|
||||
"menu.edit.ignore_list": "Ignore Files and Folders",
|
||||
"menu.edit.manage_file_extensions": "Manage File Extensions",
|
||||
"menu.edit.manage_tags": "Manage Tags",
|
||||
@@ -195,6 +198,11 @@
|
||||
"sorting.direction.ascending": "Ascending",
|
||||
"sorting.direction.descending": "Descending",
|
||||
"splash.opening_library": "Opening Library \"{library_path}\"...",
|
||||
"status.deleted_file_plural": "Deleted {count} files!",
|
||||
"status.deleted_file_singular": "Deleted 1 file!",
|
||||
"status.deleted_none": "No files deleted.",
|
||||
"status.deleted_partial_warning": "Only deleted {count} file(s)! Check if any of the files are currently missing or in use.",
|
||||
"status.deleting_file": "Deleting file [{i}/{count}]: \"{path}\"...",
|
||||
"status.library_backup_in_progress": "Saving Library Backup...",
|
||||
"status.library_backup_success": "Library Backup Saved at: \"{path}\" ({time_span})",
|
||||
"status.library_closed": "Library Closed ({time_span})",
|
||||
@@ -230,6 +238,18 @@
|
||||
"tag.shorthand": "Shorthand",
|
||||
"tag.tag_name_required": "Tag Name (Required)",
|
||||
"tag.view_limit": "View Limit:",
|
||||
"trash.context.ambiguous": "Move file(s) to {trash_term}",
|
||||
"trash.context.plural": "Move files to {trash_term}",
|
||||
"trash.context.singular": "Move file to {trash_term}",
|
||||
"trash.dialog.disambiguation_warning.plural": "This will remove them from TagStudio <i>AND</i> your file system!",
|
||||
"trash.dialog.disambiguation_warning.singular": "This will remove it from TagStudio <i>AND</i> your file system!",
|
||||
"trash.dialog.move.confirmation.plural": "Are you sure you want to move these {count} files to the {trash_term}?",
|
||||
"trash.dialog.move.confirmation.singular": "Are you sure you want to move this file to the {trash_term}?",
|
||||
"trash.dialog.permanent_delete_warning": "<b>WARNING!</b> If this file can't be moved to the {trash_term}, <b>it will be <b>permanently deleted!</b>",
|
||||
"trash.dialog.title.plural": "Delete Files",
|
||||
"trash.dialog.title.singular": "Delete File",
|
||||
"trash.name.generic": "Trash",
|
||||
"trash.name.windows": "Recycle Bin",
|
||||
"view.size.0": "Mini",
|
||||
"view.size.1": "Small",
|
||||
"view.size.2": "Medium",
|
||||
|
||||
30
tagstudio/src/qt/helpers/file_deleter.py
Normal file
30
tagstudio/src/qt/helpers/file_deleter.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright (C) 2025 Travis Abendshien (CyanVoxel).
|
||||
# Licensed under the GPL-3.0 License.
|
||||
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from send2trash import send2trash
|
||||
|
||||
logging.basicConfig(format="%(message)s", level=logging.INFO)
|
||||
|
||||
|
||||
def delete_file(path: str | Path) -> bool:
|
||||
"""Send a file to the system trash.
|
||||
|
||||
Args:
|
||||
path (str | Path): The path of the file to delete.
|
||||
"""
|
||||
_path = Path(path)
|
||||
try:
|
||||
logging.info(f"[delete_file] Sending to Trash: {_path}")
|
||||
send2trash(_path)
|
||||
return True
|
||||
except PermissionError as e:
|
||||
logging.error(f"[delete_file][ERROR] PermissionError: {e}")
|
||||
except FileNotFoundError:
|
||||
logging.error(f"[delete_file][ERROR] File Not Found: {_path}")
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return False
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2024 Travis Abendshien (CyanVoxel).
|
||||
# Copyright (C) 2025 Travis Abendshien (CyanVoxel).
|
||||
# Licensed under the GPL-3.0 License.
|
||||
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
|
||||
|
||||
@@ -9,10 +9,17 @@ import platform
|
||||
from src.qt.translations import Translations
|
||||
|
||||
|
||||
class PlatformStrings:
|
||||
open_file_str: str = Translations["file.open_location.generic"]
|
||||
|
||||
def open_file_str() -> str:
|
||||
if platform.system() == "Windows":
|
||||
open_file_str = Translations["file.open_location.windows"]
|
||||
return Translations["file.open_location.windows"]
|
||||
elif platform.system() == "Darwin":
|
||||
open_file_str = Translations["file.open_location.mac"]
|
||||
return Translations["file.open_location.mac"]
|
||||
else:
|
||||
return Translations["file.open_location.generic"]
|
||||
|
||||
|
||||
def trash_term() -> str:
|
||||
if platform.system() == "Windows":
|
||||
return Translations["trash.name.windows"]
|
||||
else:
|
||||
return Translations["trash.name.generic"]
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
"""A Qt driver for TagStudio."""
|
||||
|
||||
import contextlib
|
||||
import ctypes
|
||||
import dataclasses
|
||||
import math
|
||||
@@ -67,6 +68,7 @@ from src.core.library.alchemy.enums import (
|
||||
from src.core.library.alchemy.fields import _FieldID
|
||||
from src.core.library.alchemy.library import Entry, LibraryStatus
|
||||
from src.core.media_types import MediaCategories
|
||||
from src.core.palette import ColorType, UiColor, get_ui_color
|
||||
from src.core.query_lang.util import ParsingError
|
||||
from src.core.ts_core import TagStudioCore
|
||||
from src.core.utils.refresh_dir import RefreshDirTracker
|
||||
@@ -74,6 +76,7 @@ from src.core.utils.web import strip_web_protocol
|
||||
from src.qt.cache_manager import CacheManager
|
||||
from src.qt.flowlayout import FlowLayout
|
||||
from src.qt.helpers.custom_runnable import CustomRunnable
|
||||
from src.qt.helpers.file_deleter import delete_file
|
||||
from src.qt.helpers.function_iterator import FunctionIterator
|
||||
from src.qt.main_window import Ui_MainWindow
|
||||
from src.qt.modals.about import AboutModal
|
||||
@@ -86,6 +89,7 @@ from src.qt.modals.fix_unlinked import FixUnlinkedEntriesModal
|
||||
from src.qt.modals.folders_to_tags import FoldersToTagsModal
|
||||
from src.qt.modals.tag_database import TagDatabasePanel
|
||||
from src.qt.modals.tag_search import TagSearchPanel
|
||||
from src.qt.platform_strings import trash_term
|
||||
from src.qt.resource_manager import ResourceManager
|
||||
from src.qt.splash import Splash
|
||||
from src.qt.translations import Translations
|
||||
@@ -498,6 +502,17 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
edit_menu.addSeparator()
|
||||
|
||||
self.delete_file_action = QAction(menu_bar)
|
||||
Translations.translate_qobject(
|
||||
self.delete_file_action, "menu.delete_selected_files_ambiguous", trash_term=trash_term()
|
||||
)
|
||||
self.delete_file_action.triggered.connect(lambda f="": self.delete_files_callback(f))
|
||||
self.delete_file_action.setShortcut(QtCore.Qt.Key.Key_Delete)
|
||||
self.delete_file_action.setEnabled(False)
|
||||
edit_menu.addAction(self.delete_file_action)
|
||||
|
||||
edit_menu.addSeparator()
|
||||
|
||||
self.manage_file_ext_action = QAction(menu_bar)
|
||||
Translations.translate_qobject(
|
||||
self.manage_file_ext_action, "menu.edit.manage_file_extensions"
|
||||
@@ -839,10 +854,13 @@ class QtDriver(DriverMixin, QObject):
|
||||
|
||||
self.main_window.setWindowTitle(self.base_title)
|
||||
|
||||
self.selected = []
|
||||
self.frame_content = []
|
||||
self.selected.clear()
|
||||
self.frame_content.clear()
|
||||
[x.set_mode(None) for x in self.item_thumbs]
|
||||
|
||||
self.set_clipboard_menu_viability()
|
||||
self.set_select_actions_visibility()
|
||||
|
||||
self.preview_panel.update_widgets()
|
||||
self.main_window.toggle_landing_page(enabled=True)
|
||||
self.main_window.pagination.setHidden(True)
|
||||
@@ -937,6 +955,141 @@ class QtDriver(DriverMixin, QObject):
|
||||
for entry_id in self.selected:
|
||||
self.lib.add_tags_to_entry(entry_id, tag_ids)
|
||||
|
||||
def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = None):
|
||||
"""Callback to send on or more files to the system trash.
|
||||
|
||||
If 0-1 items are currently selected, the origin_path is used to delete the file
|
||||
from the originating context menu item.
|
||||
If there are currently multiple items selected,
|
||||
then the selection buffer is used to determine the files to be deleted.
|
||||
|
||||
Args:
|
||||
origin_path(str): The file path associated with the widget making the call.
|
||||
May or may not be the file targeted, depending on the selection rules.
|
||||
origin_id(id): The entry ID associated with the widget making the call.
|
||||
"""
|
||||
entry: Entry | None = None
|
||||
pending: list[tuple[int, Path]] = []
|
||||
deleted_count: int = 0
|
||||
|
||||
if len(self.selected) <= 1 and origin_path:
|
||||
origin_id_ = origin_id
|
||||
if not origin_id_:
|
||||
with contextlib.suppress(IndexError):
|
||||
origin_id_ = self.selected[0]
|
||||
|
||||
pending.append((origin_id_, Path(origin_path)))
|
||||
elif (len(self.selected) > 1) or (len(self.selected) <= 1):
|
||||
for item in self.selected:
|
||||
entry = self.lib.get_entry(item)
|
||||
filepath: Path = entry.path
|
||||
pending.append((item, filepath))
|
||||
|
||||
if pending:
|
||||
return_code = self.delete_file_confirmation(len(pending), pending[0][1])
|
||||
# If there was a confirmation and not a cancellation
|
||||
if (
|
||||
return_code == QMessageBox.ButtonRole.DestructiveRole.value
|
||||
and return_code != QMessageBox.ButtonRole.ActionRole.value
|
||||
):
|
||||
for i, tup in enumerate(pending):
|
||||
e_id, f = tup
|
||||
if (origin_path == f) or (not origin_path):
|
||||
self.preview_panel.thumb.stop_file_use()
|
||||
if delete_file(self.lib.library_dir / f):
|
||||
self.main_window.statusbar.showMessage(
|
||||
Translations.translate_formatted(
|
||||
"status.deleting_file", i=i, count=len(pending), path=f
|
||||
)
|
||||
)
|
||||
self.main_window.statusbar.repaint()
|
||||
self.lib.remove_entries([e_id])
|
||||
|
||||
deleted_count += 1
|
||||
self.selected.clear()
|
||||
|
||||
if deleted_count > 0:
|
||||
self.filter_items()
|
||||
self.preview_panel.update_widgets()
|
||||
|
||||
if len(self.selected) <= 1 and deleted_count == 0:
|
||||
self.main_window.statusbar.showMessage(Translations["status.deleted_none"])
|
||||
elif len(self.selected) <= 1 and deleted_count == 1:
|
||||
self.main_window.statusbar.showMessage(
|
||||
Translations.translate_formatted("status.deleted_file_plural", count=deleted_count)
|
||||
)
|
||||
elif len(self.selected) > 1 and deleted_count == 0:
|
||||
self.main_window.statusbar.showMessage(Translations["status.deleted_none"])
|
||||
elif len(self.selected) > 1 and deleted_count < len(self.selected):
|
||||
self.main_window.statusbar.showMessage(
|
||||
Translations.translate_formatted(
|
||||
"status.deleted_partial_warning", count=deleted_count
|
||||
)
|
||||
)
|
||||
elif len(self.selected) > 1 and deleted_count == len(self.selected):
|
||||
self.main_window.statusbar.showMessage(
|
||||
Translations.translate_formatted("status.deleted_file_plural", count=deleted_count)
|
||||
)
|
||||
self.main_window.statusbar.repaint()
|
||||
|
||||
def delete_file_confirmation(self, count: int, filename: Path | None = None) -> int:
|
||||
"""A confirmation dialogue box for deleting files.
|
||||
|
||||
Args:
|
||||
count(int): The number of files to be deleted.
|
||||
filename(Path | None): The filename to show if only one file is to be deleted.
|
||||
"""
|
||||
# NOTE: Windows + send2trash will PERMANENTLY delete files which cannot be moved to the
|
||||
# Recycle Bin. This is done without any warning, so this message is currently the
|
||||
# best way I've got to inform the user.
|
||||
# https://github.com/arsenetar/send2trash/issues/28
|
||||
# This warning is applied to all platforms until at least macOS and Linux can be verified
|
||||
# to not exhibit this same behavior.
|
||||
perm_warning_msg = Translations.translate_formatted(
|
||||
"trash.dialog.permanent_delete_warning", trash_term=trash_term()
|
||||
)
|
||||
perm_warning: str = (
|
||||
f"<h4 style='color: {get_ui_color(ColorType.PRIMARY, UiColor.RED)}'>"
|
||||
f"{perm_warning_msg}</h4>"
|
||||
)
|
||||
|
||||
msg = QMessageBox()
|
||||
msg.setStyleSheet("font-weight:normal;")
|
||||
msg.setTextFormat(Qt.TextFormat.RichText)
|
||||
msg.setWindowTitle(
|
||||
Translations["trash.title.singular"]
|
||||
if count == 1
|
||||
else Translations["trash.title.plural"]
|
||||
)
|
||||
msg.setIcon(QMessageBox.Icon.Warning)
|
||||
if count <= 1:
|
||||
msg_text = Translations.translate_formatted(
|
||||
"trash.dialog.move.confirmation.singular", trash_term=trash_term()
|
||||
)
|
||||
msg.setText(
|
||||
f"<h3>{msg_text}</h3>"
|
||||
f"<h4>{Translations["trash.dialog.disambiguation_warning.singular"]}</h4>"
|
||||
f"{filename if filename else ''}"
|
||||
f"{perm_warning}<br>"
|
||||
)
|
||||
elif count > 1:
|
||||
msg_text = Translations.translate_formatted(
|
||||
"trash.dialog.move.confirmation.plural",
|
||||
count=count,
|
||||
trash_term=trash_term(),
|
||||
)
|
||||
msg.setText(
|
||||
f"<h3>{msg_text}</h3>"
|
||||
f"<h4>{Translations["trash.dialog.disambiguation_warning.plural"]}</h4>"
|
||||
f"{perm_warning}<br>"
|
||||
)
|
||||
|
||||
yes_button: QPushButton = msg.addButton("&Yes", QMessageBox.ButtonRole.YesRole)
|
||||
msg.addButton("&No", QMessageBox.ButtonRole.NoRole)
|
||||
msg.setDefaultButton(yes_button)
|
||||
|
||||
return msg.exec()
|
||||
|
||||
def add_new_files_callback(self):
|
||||
"""Run when user initiates adding new files to the Library."""
|
||||
tracker = RefreshDirTracker(self.lib)
|
||||
@@ -1315,9 +1468,11 @@ class QtDriver(DriverMixin, QObject):
|
||||
if self.selected:
|
||||
self.add_tag_to_selected_action.setEnabled(True)
|
||||
self.clear_select_action.setEnabled(True)
|
||||
self.delete_file_action.setEnabled(True)
|
||||
else:
|
||||
self.add_tag_to_selected_action.setEnabled(False)
|
||||
self.clear_select_action.setEnabled(False)
|
||||
self.delete_file_action.setEnabled(False)
|
||||
|
||||
def update_completions_list(self, text: str) -> None:
|
||||
matches = re.search(
|
||||
@@ -1425,6 +1580,9 @@ class QtDriver(DriverMixin, QObject):
|
||||
if not entry:
|
||||
continue
|
||||
|
||||
with catch_warnings(record=True):
|
||||
item_thumb.delete_action.triggered.disconnect()
|
||||
|
||||
item_thumb.set_mode(ItemType.ENTRY)
|
||||
item_thumb.set_item_id(entry.id)
|
||||
item_thumb.show()
|
||||
@@ -1470,6 +1628,11 @@ class QtDriver(DriverMixin, QObject):
|
||||
)
|
||||
)
|
||||
)
|
||||
item_thumb.delete_action.triggered.connect(
|
||||
lambda checked=False, f=filenames[index], e_id=entry.id: self.delete_files_callback(
|
||||
f, e_id
|
||||
)
|
||||
)
|
||||
|
||||
# Restore Selected Borders
|
||||
is_selected = item_thumb.item_id in self.selected
|
||||
|
||||
@@ -29,7 +29,7 @@ from src.core.library import ItemType, Library
|
||||
from src.core.media_types import MediaCategories, MediaType
|
||||
from src.qt.flowlayout import FlowWidget
|
||||
from src.qt.helpers.file_opener import FileOpenerHelper
|
||||
from src.qt.platform_strings import PlatformStrings
|
||||
from src.qt.platform_strings import open_file_str, trash_term
|
||||
from src.qt.translations import Translations
|
||||
from src.qt.widgets.thumb_button import ThumbButton
|
||||
from src.qt.widgets.thumb_renderer import ThumbRenderer
|
||||
@@ -219,10 +219,17 @@ class ItemThumb(FlowWidget):
|
||||
open_file_action = QAction(self)
|
||||
Translations.translate_qobject(open_file_action, "file.open_file")
|
||||
open_file_action.triggered.connect(self.opener.open_file)
|
||||
open_explorer_action = QAction(PlatformStrings.open_file_str, self)
|
||||
open_explorer_action = QAction(open_file_str(), self)
|
||||
open_explorer_action.triggered.connect(self.opener.open_explorer)
|
||||
|
||||
self.delete_action = QAction(self)
|
||||
Translations.translate_qobject(
|
||||
self.delete_action, "trash.context.ambiguous", trash_term=trash_term()
|
||||
)
|
||||
|
||||
self.thumb_button.addAction(open_file_action)
|
||||
self.thumb_button.addAction(open_explorer_action)
|
||||
self.thumb_button.addAction(self.delete_action)
|
||||
|
||||
# Static Badges ========================================================
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import io
|
||||
import time
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from warnings import catch_warnings
|
||||
|
||||
import cv2
|
||||
import rawpy
|
||||
@@ -24,7 +25,8 @@ from src.qt.helpers.file_opener import FileOpenerHelper, open_file
|
||||
from src.qt.helpers.file_tester import is_readable_video
|
||||
from src.qt.helpers.qbutton_wrapper import QPushButtonWrapper
|
||||
from src.qt.helpers.rounded_pixmap_style import RoundedPixmapStyle
|
||||
from src.qt.platform_strings import PlatformStrings
|
||||
from src.qt.platform_strings import open_file_str, trash_term
|
||||
from src.qt.resource_manager import ResourceManager
|
||||
from src.qt.translations import Translations
|
||||
from src.qt.widgets.media_player import MediaPlayer
|
||||
from src.qt.widgets.thumb_renderer import ThumbRenderer
|
||||
@@ -54,7 +56,11 @@ class PreviewThumb(QWidget):
|
||||
|
||||
self.open_file_action = QAction(self)
|
||||
Translations.translate_qobject(self.open_file_action, "file.open_file")
|
||||
self.open_explorer_action = QAction(PlatformStrings.open_file_str, self)
|
||||
self.open_explorer_action = QAction(open_file_str(), self)
|
||||
self.delete_action = QAction(self)
|
||||
Translations.translate_qobject(
|
||||
self.delete_action, "trash.context.ambiguous", trash_term=trash_term()
|
||||
)
|
||||
|
||||
self.preview_img = QPushButtonWrapper()
|
||||
self.preview_img.setMinimumSize(*self.img_button_size)
|
||||
@@ -62,6 +68,7 @@ class PreviewThumb(QWidget):
|
||||
self.preview_img.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
|
||||
self.preview_img.addAction(self.open_file_action)
|
||||
self.preview_img.addAction(self.open_explorer_action)
|
||||
self.preview_img.addAction(self.delete_action)
|
||||
|
||||
self.preview_gif = QLabel()
|
||||
self.preview_gif.setMinimumSize(*self.img_button_size)
|
||||
@@ -69,10 +76,12 @@ class PreviewThumb(QWidget):
|
||||
self.preview_gif.setCursor(Qt.CursorShape.ArrowCursor)
|
||||
self.preview_gif.addAction(self.open_file_action)
|
||||
self.preview_gif.addAction(self.open_explorer_action)
|
||||
self.preview_gif.addAction(self.delete_action)
|
||||
self.preview_gif.hide()
|
||||
self.gif_buffer: QBuffer = QBuffer()
|
||||
|
||||
self.preview_vid = VideoPlayer(driver)
|
||||
self.preview_vid.addAction(self.delete_action)
|
||||
self.preview_vid.hide()
|
||||
self.thumb_renderer = ThumbRenderer(self.lib)
|
||||
self.thumb_renderer.updated.connect(lambda ts, i, s: (self.preview_img.setIcon(i)))
|
||||
@@ -355,7 +364,7 @@ class PreviewThumb(QWidget):
|
||||
update_on_ratio_change=True,
|
||||
)
|
||||
|
||||
if self.preview_img.is_connected:
|
||||
with catch_warnings(record=True):
|
||||
self.preview_img.clicked.disconnect()
|
||||
self.preview_img.clicked.connect(lambda checked=False, path=filepath: open_file(path))
|
||||
self.preview_img.is_connected = True
|
||||
@@ -367,12 +376,31 @@ class PreviewThumb(QWidget):
|
||||
self.open_file_action.triggered.connect(self.opener.open_file)
|
||||
self.open_explorer_action.triggered.connect(self.opener.open_explorer)
|
||||
|
||||
with catch_warnings(record=True):
|
||||
self.delete_action.triggered.disconnect()
|
||||
|
||||
self.delete_action.setText(
|
||||
Translations.translate_formatted("trash.context.singular", trash_term=trash_term())
|
||||
)
|
||||
self.delete_action.triggered.connect(
|
||||
lambda checked=False, f=filepath: self.driver.delete_files_callback(f)
|
||||
)
|
||||
self.delete_action.setEnabled(bool(filepath))
|
||||
|
||||
return stats
|
||||
|
||||
def hide_preview(self):
|
||||
"""Completely hide the file preview."""
|
||||
self.switch_preview("")
|
||||
|
||||
def stop_file_use(self):
|
||||
"""Stops the use of the currently previewed file. Used to release file permissions."""
|
||||
logger.info("[PreviewThumb] Stopping file use in video playback...")
|
||||
# This swaps the video out for a placeholder so the previous video's file
|
||||
# is no longer in use by this object.
|
||||
self.preview_vid.play(str(ResourceManager.get_path("placeholder_mp4")), QSize(8, 8))
|
||||
self.preview_vid.hide()
|
||||
|
||||
def resizeEvent(self, event: QResizeEvent) -> None: # noqa: N802
|
||||
self.update_image_size((self.size().width(), self.size().height()))
|
||||
return super().resizeEvent(event)
|
||||
|
||||
@@ -30,7 +30,7 @@ from PySide6.QtSvgWidgets import QSvgWidget
|
||||
from PySide6.QtWidgets import QGraphicsScene, QGraphicsView
|
||||
from src.core.enums import SettingItems
|
||||
from src.qt.helpers.file_opener import FileOpenerHelper
|
||||
from src.qt.platform_strings import PlatformStrings
|
||||
from src.qt.platform_strings import open_file_str
|
||||
from src.qt.translations import Translations
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
@@ -130,7 +130,7 @@ class VideoPlayer(QGraphicsView):
|
||||
Translations.translate_qobject(open_file_action, "file.open_file")
|
||||
open_file_action.triggered.connect(self.opener.open_file)
|
||||
|
||||
open_explorer_action = QAction(PlatformStrings.open_file_str, self)
|
||||
open_explorer_action = QAction(open_file_str(), self)
|
||||
|
||||
open_explorer_action.triggered.connect(self.opener.open_explorer)
|
||||
self.addAction(open_file_action)
|
||||
|
||||
Reference in New Issue
Block a user