Slideshow blacklist buttons, Ctrl+C copy, fix README code blocks

- BL Tag button in slideshow: opens categorized tag menu
- BL Post button in slideshow: blacklists current post
- Ctrl+C copies preview image to clipboard
- "Copy Image to Clipboard" in grid right-click menu
- Fix README code block formatting (missing closing backticks)
- Add ffmpeg back to Linux install deps
This commit is contained in:
pax 2026-04-05 14:04:15 -05:00
parent 04ffe5c602
commit ac2c15be29
3 changed files with 84 additions and 3 deletions

View File

@ -91,15 +91,18 @@ Requires Python 3.11+ and pip. Most distros ship Python but you may need to inst
**Arch / CachyOS:**
```sh
sudo pacman -S python python-pip qt6-base qt6-multimedia qt6-multimedia-ffmpeg```
sudo pacman -S python python-pip qt6-base qt6-multimedia qt6-multimedia-ffmpeg ffmpeg
```
**Ubuntu / Debian (24.04+):**
```sh
sudo apt install python3 python3-pip python3-venv libqt6multimedia6 gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav```
sudo apt install python3 python3-pip python3-venv libqt6multimedia6 gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav ffmpeg
```
**Fedora:**
```sh
sudo dnf install python3 python3-pip qt6-qtbase qt6-qtmultimedia gstreamer1-plugins-good gstreamer1-plugins-bad-free gstreamer1-libav```
sudo dnf install python3 python3-pip qt6-qtbase qt6-qtmultimedia gstreamer1-plugins-good gstreamer1-plugins-bad-free gstreamer1-libav ffmpeg
```
Then clone and install:
```sh

View File

@ -992,6 +992,8 @@ class BooruApp(QMainWindow):
show = self._stack.currentIndex() != 2
self._fullscreen_window._bookmark_btn.setVisible(show)
self._fullscreen_window._save_btn.setVisible(show)
self._fullscreen_window._bl_tag_btn.setVisible(show)
self._fullscreen_window._bl_post_btn.setVisible(show)
if show:
self._update_fullscreen_state()
@ -1041,6 +1043,7 @@ class BooruApp(QMainWindow):
if saved:
break
self._fullscreen_window.update_state(bookmarked, saved)
self._fullscreen_window.set_post_tags(post.tag_categories, post.tag_list)
else:
self._fullscreen_window.update_state(False, False)
@ -1222,6 +1225,31 @@ class BooruApp(QMainWindow):
else:
self._save_from_preview("")
def _blacklist_tag_from_slideshow(self, tag: str) -> None:
self._db.add_blacklisted_tag(tag)
self._db.set_setting("blacklist_enabled", "1")
# Clear slideshow if previewed post has this tag
idx = self._grid.selected_index
if 0 <= idx < len(self._posts) and tag in self._posts[idx].tag_list:
self._preview.clear()
if self._fullscreen_window:
self._fullscreen_window._viewer.clear()
self._fullscreen_window._video.stop()
self._status.showMessage(f"Blacklisted: {tag}")
self._do_search()
def _blacklist_post_from_slideshow(self) -> None:
idx = self._grid.selected_index
if 0 <= idx < len(self._posts):
post = self._posts[idx]
self._db.add_blacklisted_post(post.file_url)
self._preview.clear()
if self._fullscreen_window:
self._fullscreen_window._viewer.clear()
self._fullscreen_window._video.stop()
self._status.showMessage(f"Post #{post.id} blacklisted")
self._do_search()
def _open_fullscreen_preview(self) -> None:
path = self._preview._current_path
if not path:
@ -1253,6 +1281,8 @@ class BooruApp(QMainWindow):
if show_actions:
self._fullscreen_window.bookmark_requested.connect(self._bookmark_from_preview)
self._fullscreen_window.save_toggle_requested.connect(self._save_toggle_from_slideshow)
self._fullscreen_window.blacklist_tag_requested.connect(self._blacklist_tag_from_slideshow)
self._fullscreen_window.blacklist_post_requested.connect(self._blacklist_post_from_slideshow)
self._fullscreen_window.closed.connect(self._on_fullscreen_closed)
self._fullscreen_window.privacy_requested.connect(self._toggle_privacy)
# Sync video player state from preview to slideshow
@ -1363,6 +1393,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_url = menu.addAction("Copy Image URL")
copy_tags = menu.addAction("Copy Tags")
menu.addSeparator()
@ -1415,6 +1446,8 @@ class BooruApp(QMainWindow):
self._grid._thumbs[index].set_saved_locally(False)
else:
self._status.showMessage(f"#{post.id} not in library")
elif action == copy_clipboard:
self._copy_preview_to_clipboard()
elif action == copy_url:
QApplication.clipboard().setText(post.file_url)
self._status.showMessage("URL copied")
@ -1848,8 +1881,16 @@ class BooruApp(QMainWindow):
if self._preview._stack.currentIndex() == 1 and self._preview.underMouse():
self._preview._video_player._toggle_play()
return
elif key == Qt.Key.Key_C and event.modifiers() == Qt.KeyboardModifier.ControlModifier:
self._copy_preview_to_clipboard()
return
super().keyPressEvent(event)
def _copy_preview_to_clipboard(self) -> None:
if self._preview._image_viewer._pixmap and not self._preview._image_viewer._pixmap.isNull():
QApplication.clipboard().setPixmap(self._preview._image_viewer._pixmap)
self._status.showMessage("Image copied to clipboard")
# -- Bookmarks --
def _toggle_bookmark(self, index: int) -> None:

View File

@ -28,6 +28,8 @@ class FullscreenPreview(QMainWindow):
navigate = Signal(int) # direction: -1/+1 for left/right, -cols/+cols for up/down
bookmark_requested = Signal()
save_toggle_requested = Signal() # save or unsave depending on state
blacklist_tag_requested = Signal(str) # tag name
blacklist_post_requested = Signal()
privacy_requested = Signal()
closed = Signal()
@ -58,9 +60,23 @@ class FullscreenPreview(QMainWindow):
toolbar.addWidget(self._save_btn)
self._is_saved = False
self._bl_tag_btn = QPushButton("BL Tag")
self._bl_tag_btn.setFixedWidth(60)
self._bl_tag_btn.setToolTip("Blacklist a tag")
self._bl_tag_btn.clicked.connect(self._show_bl_tag_menu)
toolbar.addWidget(self._bl_tag_btn)
self._bl_post_btn = QPushButton("BL Post")
self._bl_post_btn.setFixedWidth(65)
self._bl_post_btn.setToolTip("Blacklist this post")
self._bl_post_btn.clicked.connect(self.blacklist_post_requested)
toolbar.addWidget(self._bl_post_btn)
if not show_actions:
self._bookmark_btn.hide()
self._save_btn.hide()
self._bl_tag_btn.hide()
self._bl_post_btn.hide()
toolbar.addStretch()
@ -100,6 +116,27 @@ class FullscreenPreview(QMainWindow):
self.setGeometry(target_screen.geometry())
self.showFullScreen()
_current_tags: dict[str, list[str]] = {}
_current_tag_list: list[str] = []
def set_post_tags(self, tag_categories: dict[str, list[str]], tag_list: list[str]) -> None:
self._current_tags = tag_categories
self._current_tag_list = tag_list
def _show_bl_tag_menu(self) -> None:
menu = QMenu(self)
if self._current_tags:
for category, tags in self._current_tags.items():
cat_menu = menu.addMenu(category)
for tag in tags[:30]:
cat_menu.addAction(tag)
else:
for tag in self._current_tag_list[:30]:
menu.addAction(tag)
action = menu.exec(self._bl_tag_btn.mapToGlobal(self._bl_tag_btn.rect().bottomLeft()))
if action:
self.blacklist_tag_requested.emit(action.text())
def update_state(self, bookmarked: bool, saved: bool) -> None:
self._bookmark_btn.setText("Unbookmark" if bookmarked else "Bookmark")
self._bookmark_btn.setFixedWidth(90 if bookmarked else 80)