Copy File to Clipboard everywhere, video support, wl-copy
- Renamed "Copy Image to Clipboard" to "Copy File to Clipboard" - Works for images AND videos via wl-copy with correct MIME types - Added to grid, preview, bookmarks, and library context menus - Ctrl+C shortcut works globally - Qt fallback for non-Wayland systems
This commit is contained in:
parent
84b1e738ab
commit
6e5b348ff7
@ -445,7 +445,7 @@ class BooruApp(QMainWindow):
|
||||
# Global shortcuts for preview navigation
|
||||
QShortcut(QKeySequence("Left"), self, lambda: self._navigate_preview(-1))
|
||||
QShortcut(QKeySequence("Right"), self, lambda: self._navigate_preview(1))
|
||||
QShortcut(QKeySequence("Ctrl+C"), self, self._copy_preview_to_clipboard)
|
||||
QShortcut(QKeySequence("Ctrl+C"), self, self._copy_file_to_clipboard)
|
||||
|
||||
def _setup_menu(self) -> None:
|
||||
menu = self.menuBar()
|
||||
@ -1405,7 +1405,7 @@ class BooruApp(QMainWindow):
|
||||
save_lib_new = save_lib_menu.addAction("+ New Folder...")
|
||||
|
||||
unsave_lib = menu.addAction("Unsave from Library")
|
||||
copy_clipboard = menu.addAction("Copy Image to Clipboard")
|
||||
copy_clipboard = menu.addAction("Copy File to Clipboard")
|
||||
copy_url = menu.addAction("Copy Image URL")
|
||||
copy_tags = menu.addAction("Copy Tags")
|
||||
menu.addSeparator()
|
||||
@ -1459,7 +1459,7 @@ class BooruApp(QMainWindow):
|
||||
else:
|
||||
self._status.showMessage(f"#{post.id} not in library")
|
||||
elif action == copy_clipboard:
|
||||
self._copy_preview_to_clipboard()
|
||||
self._copy_file_to_clipboard()
|
||||
elif action == copy_url:
|
||||
QApplication.clipboard().setText(post.file_url)
|
||||
self._status.showMessage("URL copied")
|
||||
@ -1895,8 +1895,9 @@ class BooruApp(QMainWindow):
|
||||
return
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def _copy_preview_to_clipboard(self) -> None:
|
||||
# Find the file path to copy
|
||||
def _copy_file_to_clipboard(self, path: str | None = None) -> None:
|
||||
"""Copy a file to clipboard. Tries wl-copy on Wayland, Qt fallback."""
|
||||
if not path:
|
||||
path = self._preview._current_path
|
||||
if not path:
|
||||
idx = self._grid.selected_index
|
||||
@ -1906,36 +1907,35 @@ class BooruApp(QMainWindow):
|
||||
if cp.exists():
|
||||
path = str(cp)
|
||||
if not path or not Path(path).exists():
|
||||
self._status.showMessage(f"{len(self._posts)} results — Nothing to copy")
|
||||
self._status.showMessage("Nothing to copy")
|
||||
return
|
||||
|
||||
# Try wl-copy on Wayland, fall back to Qt clipboard
|
||||
import shutil
|
||||
if shutil.which("wl-copy"):
|
||||
import subprocess
|
||||
mime = "image/png"
|
||||
ext = Path(path).suffix.lower()
|
||||
if ext in (".jpg", ".jpeg"):
|
||||
mime = "image/jpeg"
|
||||
elif ext == ".gif":
|
||||
mime = "image/gif"
|
||||
elif ext == ".webp":
|
||||
mime = "image/webp"
|
||||
_MIMES = {
|
||||
".jpg": "image/jpeg", ".jpeg": "image/jpeg",
|
||||
".png": "image/png", ".gif": "image/gif",
|
||||
".webp": "image/webp", ".mp4": "video/mp4",
|
||||
".webm": "video/webm", ".mkv": "video/x-matroska",
|
||||
".avi": "video/x-msvideo", ".mov": "video/quicktime",
|
||||
}
|
||||
mime = _MIMES.get(Path(path).suffix.lower(), "application/octet-stream")
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
subprocess.run(["wl-copy", "--type", mime], stdin=f, timeout=5)
|
||||
self._status.showMessage(f"{len(self._posts)} results — Copied to clipboard")
|
||||
subprocess.run(["wl-copy", "--type", mime], stdin=f, timeout=10)
|
||||
self._status.showMessage(f"Copied to clipboard: {Path(path).name}")
|
||||
return
|
||||
except Exception as e:
|
||||
log.warning(f"wl-copy failed: {e}")
|
||||
|
||||
# Qt fallback
|
||||
# Qt fallback (images only)
|
||||
pix = QPixmap(path)
|
||||
if not pix.isNull():
|
||||
QApplication.clipboard().setPixmap(pix)
|
||||
self._status.showMessage(f"{len(self._posts)} results — Copied to clipboard")
|
||||
self._status.showMessage(f"Copied to clipboard: {Path(path).name}")
|
||||
else:
|
||||
self._status.showMessage(f"{len(self._posts)} results — Nothing to copy")
|
||||
self._status.showMessage("Nothing to copy")
|
||||
|
||||
# -- Bookmarks --
|
||||
|
||||
|
||||
@ -230,6 +230,7 @@ class BookmarksView(QWidget):
|
||||
save_lib_menu.addSeparator()
|
||||
save_lib_new = save_lib_menu.addAction("+ New Folder...")
|
||||
|
||||
copy_file = menu.addAction("Copy File to Clipboard")
|
||||
copy_url = menu.addAction("Copy Image URL")
|
||||
copy_tags = menu.addAction("Copy Tags")
|
||||
|
||||
@ -276,6 +277,22 @@ class BookmarksView(QWidget):
|
||||
if dest:
|
||||
import shutil
|
||||
shutil.copy2(src, dest)
|
||||
elif action == copy_file:
|
||||
path = fav.cached_path
|
||||
if path and Path(path).exists():
|
||||
import shutil, subprocess
|
||||
if shutil.which("wl-copy"):
|
||||
_MIMES = {".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png",
|
||||
".gif": "image/gif", ".webp": "image/webp", ".mp4": "video/mp4",
|
||||
".webm": "video/webm"}
|
||||
mime = _MIMES.get(Path(path).suffix.lower(), "application/octet-stream")
|
||||
with open(path, "rb") as f:
|
||||
subprocess.run(["wl-copy", "--type", mime], stdin=f, timeout=10)
|
||||
else:
|
||||
from PySide6.QtGui import QPixmap
|
||||
pix = QPixmap(path)
|
||||
if not pix.isNull():
|
||||
QApplication.clipboard().setPixmap(pix)
|
||||
elif action == copy_url:
|
||||
QApplication.clipboard().setText(fav.file_url)
|
||||
elif action == copy_tags:
|
||||
|
||||
@ -307,6 +307,7 @@ class LibraryView(QWidget):
|
||||
open_default = menu.addAction("Open in Default App")
|
||||
open_folder = menu.addAction("Open Containing Folder")
|
||||
menu.addSeparator()
|
||||
copy_file = menu.addAction("Copy File to Clipboard")
|
||||
copy_path = menu.addAction("Copy File Path")
|
||||
menu.addSeparator()
|
||||
delete_action = menu.addAction("Delete from Library")
|
||||
@ -319,6 +320,23 @@ class LibraryView(QWidget):
|
||||
QDesktopServices.openUrl(QUrl.fromLocalFile(str(filepath)))
|
||||
elif action == open_folder:
|
||||
QDesktopServices.openUrl(QUrl.fromLocalFile(str(filepath.parent)))
|
||||
elif action == copy_file:
|
||||
import shutil, subprocess
|
||||
if shutil.which("wl-copy"):
|
||||
_MIMES = {".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png",
|
||||
".gif": "image/gif", ".webp": "image/webp", ".mp4": "video/mp4",
|
||||
".webm": "video/webm"}
|
||||
mime = _MIMES.get(filepath.suffix.lower(), "application/octet-stream")
|
||||
try:
|
||||
with open(filepath, "rb") as f:
|
||||
subprocess.run(["wl-copy", "--type", mime], stdin=f, timeout=10)
|
||||
except Exception as e:
|
||||
log.warning(f"wl-copy failed: {e}")
|
||||
else:
|
||||
from PySide6.QtGui import QPixmap as _QP
|
||||
pix = _QP(str(filepath))
|
||||
if not pix.isNull():
|
||||
QApplication.clipboard().setPixmap(pix)
|
||||
elif action == copy_path:
|
||||
QApplication.clipboard().setText(str(filepath))
|
||||
elif action == delete_action:
|
||||
|
||||
@ -681,7 +681,7 @@ class ImagePreview(QWidget):
|
||||
save_new = save_menu.addAction("+ New Folder...")
|
||||
|
||||
menu.addSeparator()
|
||||
copy_image = menu.addAction("Copy Image to Clipboard")
|
||||
copy_image = menu.addAction("Copy File to Clipboard")
|
||||
open_action = menu.addAction("Open in Default App")
|
||||
browser_action = menu.addAction("Open in Browser")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user