Some temp linux icons I suppose.

This commit is contained in:
DazedAnon 2026-06-13 15:25:21 -05:00
parent 80d203ec06
commit 9ff0a0c2c7
10 changed files with 197 additions and 58 deletions

View file

@ -13,6 +13,7 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QThread from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QThread
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from gui.platform_glyph import platform_glyph
from dotenv import load_dotenv, set_key, dotenv_values from dotenv import load_dotenv, set_key, dotenv_values
from gui.rpgmaker_tab import RPGMakerTab from gui.rpgmaker_tab import RPGMakerTab
@ -95,7 +96,7 @@ class ModelFetchThread(QThread):
def create_section_header(title): def create_section_header(title):
"""Create a clean section header without boxes.""" """Create a clean section header without boxes."""
label = QLabel(title) label = QLabel(platform_glyph(title))
label.setStyleSheet(""" label.setStyleSheet("""
QLabel { QLabel {
font-size: 13px; font-size: 13px;
@ -247,29 +248,13 @@ class ConfigTab(QWidget):
def create_nav_button(self, icon_text, tooltip): def create_nav_button(self, icon_text, tooltip):
"""Create a navigation button for the top bar.""" """Create a navigation button for the top bar."""
from gui.platform_glyph import configure_nav_toolbutton
btn = QToolButton() btn = QToolButton()
btn.setText(icon_text)
btn.setToolTip(tooltip) btn.setToolTip(tooltip)
btn.setFixedSize(50, 50) btn.setFixedSize(50, 50)
btn.setCheckable(True) btn.setCheckable(True)
btn.setStyleSheet(""" configure_nav_toolbutton(btn, icon_text, horizontal=True)
QToolButton {
background-color: transparent;
border: none;
border-bottom: 3px solid transparent;
color: #cccccc;
font-size: 24px;
padding: 5px;
}
QToolButton:hover {
background-color: #3e3e42;
}
QToolButton:checked {
background-color: #37373d;
border-bottom: 3px solid #007acc;
color: #ffffff;
}
""")
return btn return btn
def switch_page(self, index): def switch_page(self, index):
@ -611,7 +596,7 @@ class ConfigTab(QWidget):
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setSpacing(10) button_layout.setSpacing(10)
reset_button = QPushButton("🔄 Reset to Defaults") reset_button = QPushButton(platform_glyph("🔄 Reset to Defaults"))
reset_button.clicked.connect(self.reset_to_defaults_with_save) reset_button.clicked.connect(self.reset_to_defaults_with_save)
reset_button.setMinimumHeight(32) reset_button.setMinimumHeight(32)

View file

@ -8,6 +8,7 @@ from PyQt5.QtWidgets import (
QPushButton, QLabel, QMessageBox, QSpinBox, QFrame, QComboBox QPushButton, QLabel, QMessageBox, QSpinBox, QFrame, QComboBox
) )
from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtCore import Qt, pyqtSignal
from gui.platform_glyph import platform_glyph
try: try:
from .config_integration import ConfigIntegration from .config_integration import ConfigIntegration
@ -17,7 +18,7 @@ except ImportError:
def create_section_label(text): def create_section_label(text):
"""Create a section label for grouping settings.""" """Create a section label for grouping settings."""
label = QLabel(text) label = QLabel(platform_glyph(text))
label.setStyleSheet(""" label.setStyleSheet("""
QLabel { QLabel {
font-size: 12px; font-size: 12px;
@ -247,7 +248,7 @@ class CSVTab(QWidget):
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setSpacing(10) button_layout.setSpacing(10)
self.reset_button = QPushButton("🔄 Reset to Defaults") self.reset_button = QPushButton(platform_glyph("🔄 Reset to Defaults"))
self.reset_button.clicked.connect(self.reset_to_defaults_with_message) self.reset_button.clicked.connect(self.reset_to_defaults_with_message)
self.reset_button.setMaximumWidth(180) self.reset_button.setMaximumWidth(180)
self.reset_button.setMinimumHeight(32) self.reset_button.setMinimumHeight(32)

View file

@ -7,6 +7,7 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.QtCore import Qt, pyqtSignal, QTimer from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QTextCursor, QFont, QTextCharFormat from PyQt5.QtGui import QTextCursor, QFont, QTextCharFormat
from gui.platform_glyph import platform_glyph
from pathlib import Path from pathlib import Path
import datetime import datetime
import html import html
@ -34,7 +35,7 @@ class LogViewer(QWidget):
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
# Simple header to match left-side styling (use same look as create_section_header) # Simple header to match left-side styling (use same look as create_section_header)
header = QLabel("📝 Translation Log") header = QLabel(platform_glyph("📝 Translation Log"))
header.setStyleSheet(""" header.setStyleSheet("""
QLabel { QLabel {
font-size: 13px; font-size: 13px;

View file

@ -455,29 +455,13 @@ class DazedMTLGUI(QMainWindow):
def create_nav_button(self, icon_text, tooltip): def create_nav_button(self, icon_text, tooltip):
"""Create a navigation button for the sidebar.""" """Create a navigation button for the sidebar."""
from gui.platform_glyph import configure_nav_toolbutton
btn = QToolButton() btn = QToolButton()
btn.setText(icon_text)
btn.setToolTip(tooltip) btn.setToolTip(tooltip)
btn.setFixedSize(60, 50) btn.setFixedSize(60, 50)
btn.setCheckable(True) btn.setCheckable(True)
btn.setStyleSheet(""" configure_nav_toolbutton(btn, icon_text, horizontal=False)
QToolButton {
background-color: transparent;
border: none;
border-left: 3px solid transparent;
color: #cccccc;
font-size: 24px;
padding: 5px;
}
QToolButton:hover {
background-color: #3e3e42;
}
QToolButton:checked {
background-color: #37373d;
border-left: 3px solid #007acc;
color: #ffffff;
}
""")
return btn return btn
def switch_page(self, index): def switch_page(self, index):

162
gui/platform_glyph.py Normal file
View file

@ -0,0 +1,162 @@
"""Linux fallbacks for emoji that PyQt5 often cannot render (tofu boxes).
Only replaces glyphs known to fail on typical Linux font stacks.
Windows/macOS get the original strings unchanged.
"""
from __future__ import annotations
import re
import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QColor, QFont, QIcon, QPainter, QPixmap
# Toolbar buttons, section headers, mixed labels
_LINUX_EMOJI_FALLBACKS: dict[str, str] = {
"\U00002795": "+", # add
"\U0001F4C1": "\u2302", # 📁 folder → ⌂
"\U0001F4C2": "\u2302", # 📂 open folder
"\U0001F504": "\u21bb", # 🔄 refresh → ↻
"\U0001F4DD": "", # 📝 memo (section headers)
"\U0001F6D1": "\u25a0", # 🛑 stop → ■
"\U0001F4E5": "\u2193", # 📥 inbox tray → ↓
"\U0001F527": "\u2699", # 🔧 wrench → ⚙
"\U0001F511": "", # 🔑 key (section headers)
"\U0001F310": "", # 🌐 globe (section headers)
"\U0001F5A5": "", # 🖥 desktop (section headers)
"\U00002699\uFE0F": "\u2699", # ⚙️ → ⚙
"\U0000270F\uFE0F": "\u270E", # ✏️ → ✎
}
# Icon-only nav tabs — never empty; BMP symbols so metrics match across the bar
_LINUX_NAV_FALLBACKS: dict[str, str] = {
"\U0001F310": "\u25ce", # 🌐 Translation → ◎
"\U0001F527": "\u2699", # 🔧 General → ⚙
"\U0001F3AE": "\u25c6", # 🎮 MV/MZ → ◆
"\U0001F43A": "\u25c8", # 🐺 Wolf → ◈
"\U0001F4C4": "\u2630", # 📄 CSV → ☰
"\U00002694\uFE0F": "\u2694", # ⚔️ SRPG → ⚔
"\U00002694": "\u2694",
"\U0001F504": "\u21bb", # 🔄 Update → ↻
"\U00002699\uFE0F": "\u2699", # ⚙️ Config → ⚙
"\U0000270F\uFE0F": "\u270E", # ✏️ Rewrite → ✎
"\U000026A1": "\u26a1", # ⚡ Workflow
}
def _apply_fallbacks(text: str, mapping: dict[str, str]) -> str:
out = text
for emoji, replacement in mapping.items():
out = out.replace(emoji, replacement)
out = re.sub(r" +", " ", out)
return out.strip()
def platform_glyph(text: str) -> str:
"""Return UI text with unsupported emoji swapped on Linux only."""
if not sys.platform.startswith("linux") or not text:
return text
return _apply_fallbacks(text, _LINUX_EMOJI_FALLBACKS)
def platform_nav_glyph(icon: str) -> str:
"""Linux fallback for icon-only nav tabs (never returns empty)."""
if not sys.platform.startswith("linux") or not icon:
return icon
out = _apply_fallbacks(icon, _LINUX_NAV_FALLBACKS)
if not out:
out = _apply_fallbacks(icon, _LINUX_EMOJI_FALLBACKS)
return out or icon
def _linux_nav_pixmap(glyph: str, *, size: int, font_px: int, color: QColor) -> QPixmap:
pixmap = QPixmap(size, size)
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
font = QFont("DejaVu Sans")
font.setPixelSize(font_px)
painter.setFont(font)
painter.setPen(color)
painter.drawText(pixmap.rect(), Qt.AlignCenter, glyph)
painter.end()
return pixmap
def _linux_nav_icon(icon_text: str, *, size: int, font_px: int) -> QIcon:
"""Render a nav glyph into a fixed-size pixmap so every tab aligns the same."""
glyph = platform_nav_glyph(icon_text)
icon = QIcon()
gray = _linux_nav_pixmap(glyph, size=size, font_px=font_px, color=QColor("#cccccc"))
white = _linux_nav_pixmap(glyph, size=size, font_px=font_px, color=QColor("#ffffff"))
icon.addPixmap(gray, QIcon.Normal, QIcon.Off)
icon.addPixmap(gray, QIcon.Disabled, QIcon.Off)
icon.addPixmap(white, QIcon.Active, QIcon.Off)
icon.addPixmap(white, QIcon.Selected, QIcon.Off)
return icon
def _nav_toolbutton_stylesheet(*, horizontal: bool, icon_only: bool) -> str:
border_prop = "border-bottom" if horizontal else "border-left"
if icon_only:
return f"""
QToolButton {{
background-color: transparent;
border: none;
{border_prop}: 3px solid transparent;
color: #cccccc;
padding: 0px;
margin: 0px;
}}
QToolButton:hover {{
background-color: #3e3e42;
}}
QToolButton:checked {{
background-color: #37373d;
{border_prop}: 3px solid #007acc;
color: #ffffff;
}}
"""
font_size = "18px" if sys.platform.startswith("linux") else "24px"
return f"""
QToolButton {{
background-color: transparent;
border: none;
{border_prop}: 3px solid transparent;
color: #cccccc;
font-size: {font_size};
font-family: 'DejaVu Sans Mono', monospace;
padding: 0px;
margin: 0px;
}}
QToolButton:hover {{
background-color: #3e3e42;
}}
QToolButton:checked {{
background-color: #37373d;
{border_prop}: 3px solid #007acc;
color: #ffffff;
}}
"""
def configure_nav_toolbutton(btn, icon_text: str, *, horizontal: bool = False) -> None:
"""Apply nav icon — on Linux render BMP symbols into fixed pixmaps for alignment."""
if sys.platform.startswith("linux"):
# Scale to the button cell (leave room for the 3px active border).
icon_dim = max(28, min(btn.width(), btn.height()) - 8)
font_px = max(22, int(icon_dim * 0.78))
btn.setIcon(_linux_nav_icon(icon_text, size=icon_dim, font_px=font_px))
btn.setIconSize(QSize(icon_dim, icon_dim))
btn.setText("")
btn.setToolButtonStyle(Qt.ToolButtonIconOnly)
btn.setStyleSheet(_nav_toolbutton_stylesheet(horizontal=horizontal, icon_only=True))
return
btn.setIcon(QIcon())
btn.setText(icon_text)
btn.setToolButtonStyle(Qt.ToolButtonTextOnly)
btn.setStyleSheet(_nav_toolbutton_stylesheet(horizontal=horizontal, icon_only=False))

View file

@ -10,6 +10,7 @@ from PyQt5.QtWidgets import (
QTextEdit, QSpinBox, QFrame, QGridLayout QTextEdit, QSpinBox, QFrame, QGridLayout
) )
from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtCore import Qt, pyqtSignal
from gui.platform_glyph import platform_glyph
try: try:
from .config_integration import ConfigIntegration from .config_integration import ConfigIntegration
@ -25,8 +26,8 @@ except Exception:
def create_section_label(text): def create_section_label(text):
"""Create a section label for grouping checkboxes.""" """Create a section label for grouping settings."""
label = QLabel(text) label = QLabel(platform_glyph(text))
label.setStyleSheet(""" label.setStyleSheet("""
QLabel { QLabel {
font-size: 13px; font-size: 13px;
@ -456,7 +457,7 @@ class RPGMakerTab(QWidget):
# Reset button # Reset button
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
self.reset_button = QPushButton("🔄 Reset to Defaults") self.reset_button = QPushButton(platform_glyph("🔄 Reset to Defaults"))
self.reset_button.clicked.connect(self.reset_to_defaults_with_message) self.reset_button.clicked.connect(self.reset_to_defaults_with_message)
self.reset_button.setMinimumHeight(32) self.reset_button.setMinimumHeight(32)
self.reset_button.setMaximumWidth(160) self.reset_button.setMaximumWidth(160)

View file

@ -9,6 +9,7 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
import re import re
from gui.platform_glyph import platform_glyph
try: try:
import set_defaults import set_defaults
@ -19,7 +20,7 @@ except Exception:
def create_section_label(text): def create_section_label(text):
"""Create a styled section header label.""" """Create a styled section header label."""
label = QLabel(text) label = QLabel(platform_glyph(text))
label.setStyleSheet("font-size: 12px; font-weight: bold; color: #007acc; padding: 2px 0px;") label.setStyleSheet("font-size: 12px; font-weight: bold; color: #007acc; padding: 2px 0px;")
return label return label
@ -83,7 +84,7 @@ class SRPGTab(QWidget):
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setSpacing(10) button_layout.setSpacing(10)
self.reset_btn = QPushButton("🔄 Reset to Defaults") self.reset_btn = QPushButton(platform_glyph("🔄 Reset to Defaults"))
self.reset_btn.clicked.connect(self.reset_to_defaults_with_message) self.reset_btn.clicked.connect(self.reset_to_defaults_with_message)
self.reset_btn.setMaximumWidth(180) self.reset_btn.setMaximumWidth(180)
self.reset_btn.setMinimumHeight(32) self.reset_btn.setMinimumHeight(32)

View file

@ -31,6 +31,7 @@ from PyQt5.QtWidgets import QSizePolicy
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread, QMutex, QProcess, QEvent, QRect, QSettings from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread, QMutex, QProcess, QEvent, QRect, QSettings
from PyQt5.QtGui import QFont from PyQt5.QtGui import QFont
from gui.log_viewer import LogViewer from gui.log_viewer import LogViewer
from gui.platform_glyph import platform_glyph
def _strip_ansi(text): def _strip_ansi(text):
@ -41,7 +42,7 @@ def _strip_ansi(text):
def create_section_header(title): def create_section_header(title):
"""Create a clean section header without boxes.""" """Create a clean section header without boxes."""
label = QLabel(title) label = QLabel(platform_glyph(title))
label.setStyleSheet(""" label.setStyleSheet("""
QLabel { QLabel {
font-size: 13px; font-size: 13px;
@ -849,7 +850,7 @@ class TranslationTab(QWidget):
deselect_all_btn.setStyleSheet(icon_button_style) deselect_all_btn.setStyleSheet(icon_button_style)
file_buttons.addWidget(deselect_all_btn) file_buttons.addWidget(deselect_all_btn)
add_files_btn = QPushButton("") add_files_btn = QPushButton(platform_glyph(""))
add_files_btn.setToolTip("Add files to translate") add_files_btn.setToolTip("Add files to translate")
add_files_btn.clicked.connect(self.add_input_files) add_files_btn.clicked.connect(self.add_input_files)
add_files_btn.setStyleSheet(icon_button_style) add_files_btn.setStyleSheet(icon_button_style)
@ -861,13 +862,13 @@ class TranslationTab(QWidget):
remove_files_btn.setStyleSheet(icon_button_style) remove_files_btn.setStyleSheet(icon_button_style)
file_buttons.addWidget(remove_files_btn) file_buttons.addWidget(remove_files_btn)
open_folder_btn = QPushButton("📁") open_folder_btn = QPushButton(platform_glyph("📁"))
open_folder_btn.setToolTip("Open files folder in explorer") open_folder_btn.setToolTip("Open files folder in explorer")
open_folder_btn.clicked.connect(self.open_input_folder) open_folder_btn.clicked.connect(self.open_input_folder)
open_folder_btn.setStyleSheet(icon_button_style) open_folder_btn.setStyleSheet(icon_button_style)
file_buttons.addWidget(open_folder_btn) file_buttons.addWidget(open_folder_btn)
refresh_btn = QPushButton("🔄") refresh_btn = QPushButton(platform_glyph("🔄"))
refresh_btn.setToolTip("Refresh file list") refresh_btn.setToolTip("Refresh file list")
refresh_btn.clicked.connect(self.refresh_file_lists) refresh_btn.clicked.connect(self.refresh_file_lists)
refresh_btn.setStyleSheet(icon_button_style) refresh_btn.setStyleSheet(icon_button_style)
@ -1120,12 +1121,12 @@ class TranslationTab(QWidget):
self.reset_view_button.clicked.connect(self.reset_to_file_view) self.reset_view_button.clicked.connect(self.reset_to_file_view)
self.reset_view_button.setVisible(False) self.reset_view_button.setVisible(False)
# Button to open the translations (translated) folder - icon-only # Button to open the translations (translated) folder - icon-only
self.open_translations_button = QPushButton("📂") self.open_translations_button = QPushButton(platform_glyph("📂"))
self.open_translations_button.setToolTip("Open the translated files folder") self.open_translations_button.setToolTip("Open the translated files folder")
self.open_translations_button.clicked.connect(self.open_output_folder) self.open_translations_button.clicked.connect(self.open_output_folder)
self.open_translations_button.setVisible(False) self.open_translations_button.setVisible(False)
# Sync translated/ → files/ (RPG Maker only) # Sync translated/ → files/ (RPG Maker only)
self.sync_translated_button = QPushButton("🔄") self.sync_translated_button = QPushButton(platform_glyph("🔄"))
self.sync_translated_button.setToolTip("Sync translated/ → files/\nCopy translated files back into files/ so the next phase starts from the latest state") self.sync_translated_button.setToolTip("Sync translated/ → files/\nCopy translated files back into files/ so the next phase starts from the latest state")
self.sync_translated_button.clicked.connect(self._sync_translated_to_files) self.sync_translated_button.clicked.connect(self._sync_translated_to_files)
self.sync_translated_button.setVisible(False) self.sync_translated_button.setVisible(False)
@ -1195,7 +1196,7 @@ class TranslationTab(QWidget):
# Use a clear stop-sign emoji so the glyph is rendered as a stop icon # Use a clear stop-sign emoji so the glyph is rendered as a stop icon
# and not as a colored square on some platforms. # and not as a colored square on some platforms.
self.stop_button = QPushButton("🛑") self.stop_button = QPushButton(platform_glyph("🛑"))
self.stop_button.setToolTip("Stop Translation") self.stop_button.setToolTip("Stop Translation")
self.stop_button.clicked.connect(self.stop_translation) self.stop_button.clicked.connect(self.stop_translation)
self.stop_button.setStyleSheet(stop_button_style) self.stop_button.setStyleSheet(stop_button_style)

View file

@ -9,6 +9,7 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
import re import re
from gui.platform_glyph import platform_glyph
try: try:
import set_defaults import set_defaults
CANONICAL_DEFAULTS = getattr(set_defaults, 'DEFAULTS', None) CANONICAL_DEFAULTS = getattr(set_defaults, 'DEFAULTS', None)
@ -17,7 +18,7 @@ except Exception:
def create_section_label(text): def create_section_label(text):
"""Create a styled section header label.""" """Create a styled section header label."""
label = QLabel(text) label = QLabel(platform_glyph(text))
label.setStyleSheet("font-size: 12px; font-weight: bold; color: #007acc; padding: 2px 0px;") label.setStyleSheet("font-size: 12px; font-weight: bold; color: #007acc; padding: 2px 0px;")
return label return label
@ -171,7 +172,7 @@ class WolfTab(QWidget):
button_layout = QHBoxLayout() button_layout = QHBoxLayout()
button_layout.setSpacing(10) button_layout.setSpacing(10)
self.reset_btn = QPushButton("🔄 Reset to Defaults") self.reset_btn = QPushButton(platform_glyph("🔄 Reset to Defaults"))
self.reset_btn.clicked.connect(self.reset_to_defaults_with_message) self.reset_btn.clicked.connect(self.reset_to_defaults_with_message)
self.reset_btn.setMaximumWidth(180) self.reset_btn.setMaximumWidth(180)
self.reset_btn.setMinimumHeight(32) self.reset_btn.setMinimumHeight(32)

View file

@ -444,7 +444,9 @@ def _make_btn(text: str, color: str = "#007acc") -> QPushButton:
def _make_icon_btn(icon_text: str, tooltip: str = "") -> QPushButton: def _make_icon_btn(icon_text: str, tooltip: str = "") -> QPushButton:
"""Compact icon-only button matching the Translation tab action buttons.""" """Compact icon-only button matching the Translation tab action buttons."""
btn = QPushButton(icon_text) from gui.platform_glyph import platform_glyph
btn = QPushButton(platform_glyph(icon_text))
btn.setToolTip(tooltip) btn.setToolTip(tooltip)
btn.setFont(QFont("Segoe UI", 12)) btn.setFont(QFont("Segoe UI", 12))
btn.setFixedSize(40, 36) btn.setFixedSize(40, 36)