diff --git a/booru_viewer/core/config.py b/booru_viewer/core/config.py index c91ea02..f13a0dd 100644 --- a/booru_viewer/core/config.py +++ b/booru_viewer/core/config.py @@ -97,15 +97,6 @@ def db_path() -> Path: return data_dir() / "booru.db" -# Green-on-black palette -GREEN = "#00ff00" -DARK_GREEN = "#00cc00" -DIM_GREEN = "#009900" -BG = "#000000" -BG_LIGHT = "#111111" -BG_LIGHTER = "#1a1a1a" -BORDER = "#333333" - # Defaults DEFAULT_THUMBNAIL_SIZE = (200, 200) DEFAULT_PAGE_SIZE = 40 diff --git a/booru_viewer/gui/app.py b/booru_viewer/gui/app.py index f51a8d2..d52aa61 100644 --- a/booru_viewer/gui/app.py +++ b/booru_viewer/gui/app.py @@ -9,8 +9,8 @@ import sys import threading from pathlib import Path -from PySide6.QtCore import Qt, QTimer, Signal, QObject, QUrl -from PySide6.QtGui import QPixmap, QAction, QKeySequence, QDesktopServices, QShortcut +from PySide6.QtCore import Qt, QTimer, Signal, QObject, QUrl, Property +from PySide6.QtGui import QPixmap, QAction, QKeySequence, QDesktopServices, QShortcut, QColor from PySide6.QtWidgets import ( QApplication, QMainWindow, @@ -109,6 +109,60 @@ class InfoPanel(QWidget): tag_clicked = Signal(str) + # Tag category colors. Defaults follow the booru convention (Danbooru, + # Gelbooru, etc.) so the panel reads naturally to anyone coming from a + # booru site. Each is exposed as a Qt Property so a custom.qss can + # override it via `qproperty-tagColor` selectors on + # `InfoPanel`. An empty string means "use the default text color" + # (the General category) and is preserved as a sentinel. + _tag_artist_color = QColor("#f2ac08") + _tag_character_color = QColor("#0a0") + _tag_copyright_color = QColor("#c0f") + _tag_species_color = QColor("#e44") + _tag_meta_color = QColor("#888") + _tag_lore_color = QColor("#888") + + def _get_artist(self): return self._tag_artist_color + def _set_artist(self, c): self._tag_artist_color = QColor(c) if isinstance(c, str) else c + tagArtistColor = Property(QColor, _get_artist, _set_artist) + + def _get_character(self): return self._tag_character_color + def _set_character(self, c): self._tag_character_color = QColor(c) if isinstance(c, str) else c + tagCharacterColor = Property(QColor, _get_character, _set_character) + + def _get_copyright(self): return self._tag_copyright_color + def _set_copyright(self, c): self._tag_copyright_color = QColor(c) if isinstance(c, str) else c + tagCopyrightColor = Property(QColor, _get_copyright, _set_copyright) + + def _get_species(self): return self._tag_species_color + def _set_species(self, c): self._tag_species_color = QColor(c) if isinstance(c, str) else c + tagSpeciesColor = Property(QColor, _get_species, _set_species) + + def _get_meta(self): return self._tag_meta_color + def _set_meta(self, c): self._tag_meta_color = QColor(c) if isinstance(c, str) else c + tagMetaColor = Property(QColor, _get_meta, _set_meta) + + def _get_lore(self): return self._tag_lore_color + def _set_lore(self, c): self._tag_lore_color = QColor(c) if isinstance(c, str) else c + tagLoreColor = Property(QColor, _get_lore, _set_lore) + + def _category_color(self, category: str) -> str: + """Resolve a category name to a hex color string for inline QSS use. + Returns "" for the General category (no override → use default text + color) and unrecognized categories (so callers can render them with + no color attribute set).""" + cat = (category or "").lower() + m = { + "artist": self._tag_artist_color, + "character": self._tag_character_color, + "copyright": self._tag_copyright_color, + "species": self._tag_species_color, + "meta": self._tag_meta_color, + "lore": self._tag_lore_color, + } + c = m.get(cat) + return c.name() if c is not None else "" + def __init__(self, parent: QWidget | None = None) -> None: super().__init__(parent) layout = QVBoxLayout(self) @@ -175,21 +229,12 @@ class InfoPanel(QWidget): if item.widget(): item.widget().deleteLater() - # Tag category colors - _CAT_COLORS = { - "Artist": "#f2ac08", - "Character": "#0a0", - "Copyright": "#c0f", - "Species": "#e44", - "General": "", - "Meta": "#888", - "Lore": "#888", - } - if post.tag_categories: - # Display tags grouped by category + # Display tags grouped by category. Colors come from the + # tag*Color Qt Properties so a custom.qss can override any of + # them via `InfoPanel { qproperty-tagCharacterColor: ...; }`. for category, tags in post.tag_categories.items(): - color = _CAT_COLORS.get(category, "") + color = self._category_color(category) header = QLabel(f"{category}:") header.setStyleSheet( f"font-weight: bold; margin-top: 6px; margin-bottom: 2px;" diff --git a/booru_viewer/gui/theme.py b/booru_viewer/gui/theme.py deleted file mode 100644 index f288f3a..0000000 --- a/booru_viewer/gui/theme.py +++ /dev/null @@ -1,222 +0,0 @@ -"""Green-on-black Qt6 stylesheet.""" - -from ..core.config import GREEN, DARK_GREEN, DIM_GREEN, BG, BG_LIGHT, BG_LIGHTER, BORDER - -STYLESHEET = f""" -QMainWindow, QDialog {{ - background-color: {BG}; - color: {GREEN}; -}} - -QWidget {{ - background-color: {BG}; - color: {GREEN}; - font-family: "Terminess Nerd Font Propo", "Hack Nerd Font", monospace; - font-size: 13px; -}} - -QMenuBar {{ - background-color: {BG}; - color: {GREEN}; - border-bottom: 1px solid {BORDER}; -}} - -QMenuBar::item:selected {{ - background-color: {BG_LIGHTER}; -}} - -QMenu {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; -}} - -QMenu::item:selected {{ - background-color: {BG_LIGHTER}; -}} - -QLineEdit {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - border-radius: 4px; - padding: 6px 10px; - selection-background-color: {DIM_GREEN}; - selection-color: {BG}; -}} - -QLineEdit:focus {{ - border-color: {GREEN}; -}} - -QPushButton {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - border-radius: 4px; - padding: 6px 16px; - min-height: 28px; -}} - -QPushButton:hover {{ - background-color: {BG_LIGHTER}; - border-color: {DIM_GREEN}; -}} - -QPushButton:pressed {{ - background-color: {DIM_GREEN}; - color: {BG}; -}} - -QComboBox {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - border-radius: 4px; - padding: 4px 8px; -}} - -QComboBox:hover {{ - border-color: {DIM_GREEN}; -}} - -QComboBox QAbstractItemView {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - selection-background-color: {DIM_GREEN}; - selection-color: {BG}; -}} - -QComboBox::drop-down {{ - border: none; - width: 20px; -}} - -QScrollBar:vertical {{ - background: {BG}; - width: 10px; - margin: 0; -}} - -QScrollBar::handle:vertical {{ - background: {BORDER}; - min-height: 30px; - border-radius: 5px; -}} - -QScrollBar::handle:vertical:hover {{ - background: {DIM_GREEN}; -}} - -QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{ - height: 0; -}} - -QScrollBar:horizontal {{ - background: {BG}; - height: 10px; - margin: 0; -}} - -QScrollBar::handle:horizontal {{ - background: {BORDER}; - min-width: 30px; - border-radius: 5px; -}} - -QScrollBar::handle:horizontal:hover {{ - background: {DIM_GREEN}; -}} - -QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{ - width: 0; -}} - -QLabel {{ - color: {GREEN}; -}} - -QStatusBar {{ - background-color: {BG}; - color: {DIM_GREEN}; - border-top: 1px solid {BORDER}; -}} - -QTabWidget::pane {{ - border: 1px solid {BORDER}; - background-color: {BG}; -}} - -QTabBar::tab {{ - background-color: {BG_LIGHT}; - color: {DIM_GREEN}; - border: 1px solid {BORDER}; - border-bottom: none; - padding: 6px 16px; - margin-right: 2px; -}} - -QTabBar::tab:selected {{ - color: {GREEN}; - border-color: {GREEN}; - background-color: {BG}; -}} - -QTabBar::tab:hover {{ - color: {GREEN}; - background-color: {BG_LIGHTER}; -}} - -QListWidget {{ - background-color: {BG}; - color: {GREEN}; - border: 1px solid {BORDER}; - outline: none; -}} - -QListWidget::item:selected {{ - background-color: {DIM_GREEN}; - color: {BG}; -}} - -QListWidget::item:hover {{ - background-color: {BG_LIGHTER}; -}} - -QDialogButtonBox QPushButton {{ - min-width: 80px; -}} - -QToolTip {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - padding: 4px; -}} - -QCompleter QAbstractItemView {{ - background-color: {BG_LIGHT}; - color: {GREEN}; - border: 1px solid {BORDER}; - selection-background-color: {DIM_GREEN}; - selection-color: {BG}; -}} - -QSplitter::handle {{ - background-color: {BORDER}; -}} - -QProgressBar {{ - background-color: {BG_LIGHT}; - border: 1px solid {BORDER}; - border-radius: 4px; - text-align: center; - color: {GREEN}; -}} - -QProgressBar::chunk {{ - background-color: {DIM_GREEN}; - border-radius: 3px; -}} -""" diff --git a/themes/README.md b/themes/README.md index c664dbe..b5670a0 100644 --- a/themes/README.md +++ b/themes/README.md @@ -299,6 +299,27 @@ ThumbnailWidget { } ``` +### Info Panel Tag Categories + +The tag list in the info panel groups tags by category and colors each +category. Defaults follow the booru convention (Danbooru, Gelbooru, etc.) +so the panel reads naturally to anyone coming from a booru site. Override +any of them via `qproperty-tagColor` on `InfoPanel`: + +```css +InfoPanel { + qproperty-tagArtistColor: #f2ac08; /* default: orange */ + qproperty-tagCharacterColor: #00aa00; /* default: green (booru convention) */ + qproperty-tagCopyrightColor: #cc00ff; /* default: magenta */ + qproperty-tagSpeciesColor: #ee4444; /* default: red */ + qproperty-tagMetaColor: #888888; /* default: gray */ + qproperty-tagLoreColor: #888888; /* default: gray */ +} +``` + +The General category has no color override — its tags use the panel's +default text color so they fall in line with the rest of the theme. + ## States | State | Description | @@ -314,6 +335,6 @@ ThumbnailWidget { - `selection-background-color` on `QWidget` controls the **grid thumbnail selection border** and **hover highlight** (lighter version auto-derived) - Setting a custom QSS automatically switches to the Fusion Qt style for consistent rendering -- Tag category colors (Artist, Character, etc.) in the info panel are set in code, not via QSS +- Tag category colors (Artist, Character, Copyright, Species, Meta, Lore) are QSS-controllable via `qproperty-tagColor` on `InfoPanel` — see the Info Panel Tag Categories section above - Saved dot (green) and bookmark star (yellow) are QSS-controllable via `qproperty-savedColor` and `qproperty-bookmarkedColor` on `ThumbnailWidget` - Use `QLabel { background: transparent; }` to prevent labels from getting opaque backgrounds