Diàleg «Quant a» centrat amb icona, nom gran i versió en cursiva
This commit is contained in:
@@ -100,8 +100,9 @@ if [ "$OS" = "darwin" ]; then
|
|||||||
mv "$PRODUCED" "$APP"
|
mv "$PRODUCED" "$APP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[build] sembrando games.toml en Contents/Resources…"
|
echo "[build] sembrando games.toml y icon.png en Contents/Resources…"
|
||||||
cp games.toml "$APP/Contents/Resources/games.toml"
|
cp games.toml "$APP/Contents/Resources/games.toml"
|
||||||
|
cp assets/icon.png "$APP/Contents/Resources/icon.png" # usado por el diálogo «Quant a»
|
||||||
|
|
||||||
# Bundle ad-hoc (sin Developer ID): quitamos quarantine para abrir sin fricción local.
|
# Bundle ad-hoc (sin Developer ID): quitamos quarantine para abrir sin fricción local.
|
||||||
xattr -dr com.apple.quarantine "$APP" 2>/dev/null || true
|
xattr -dr com.apple.quarantine "$APP" 2>/dev/null || true
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from PySide6.QtGui import QIcon
|
||||||
from PySide6.QtWidgets import QApplication, QMessageBox
|
from PySide6.QtWidgets import QApplication, QMessageBox
|
||||||
|
|
||||||
from .config import load_config
|
from .config import load_config
|
||||||
from .paths import config_file, data_root
|
from .paths import app_icon_path, config_file, data_root
|
||||||
from .ui.main_window import MainWindow
|
from .ui.main_window import MainWindow
|
||||||
from .ui.theme import apply_theme
|
from .ui.theme import apply_theme
|
||||||
|
|
||||||
@@ -15,6 +16,9 @@ from .ui.theme import apply_theme
|
|||||||
def main() -> int:
|
def main() -> int:
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
app.setApplicationName("jlauncher")
|
app.setApplicationName("jlauncher")
|
||||||
|
icon_path = app_icon_path()
|
||||||
|
if icon_path is not None:
|
||||||
|
app.setWindowIcon(QIcon(str(icon_path)))
|
||||||
# Tema del sistema para el posible diálogo de error previo a la ventana;
|
# Tema del sistema para el posible diálogo de error previo a la ventana;
|
||||||
# MainWindow re-aplica el modo guardado (system/light/dark) y vigila los cambios.
|
# MainWindow re-aplica el modo guardado (system/light/dark) y vigila los cambios.
|
||||||
apply_theme(app)
|
apply_theme(app)
|
||||||
|
|||||||
@@ -55,6 +55,20 @@ def macos_app_bundle() -> Path | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def app_icon_path() -> Path | None:
|
||||||
|
"""Ruta al PNG del icono para la UI (icono de ventana/Dock y diálogo «Quant a»).
|
||||||
|
|
||||||
|
En .app vive en ``Contents/Resources/icon.png``; desde fuente, en ``assets/icon.png``.
|
||||||
|
Devuelve None si no se encuentra.
|
||||||
|
"""
|
||||||
|
bundle = macos_app_bundle()
|
||||||
|
if bundle is not None:
|
||||||
|
candidate = bundle / "Contents" / "Resources" / "icon.png"
|
||||||
|
else:
|
||||||
|
candidate = base_dir() / "assets" / "icon.png"
|
||||||
|
return candidate if candidate.exists() else None
|
||||||
|
|
||||||
|
|
||||||
def support_dir() -> Path:
|
def support_dir() -> Path:
|
||||||
"""Carpeta de soporte escribible en macOS (.app); se crea si no existe."""
|
"""Carpeta de soporte escribible en macOS (.app); se crea si no existe."""
|
||||||
root = (
|
root = (
|
||||||
|
|||||||
@@ -5,10 +5,14 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from PySide6.QtCore import QEasingCurve, QPropertyAnimation, QThreadPool, Qt, QTimer
|
from PySide6.QtCore import QEasingCurve, QPropertyAnimation, QThreadPool, Qt, QTimer
|
||||||
from PySide6.QtGui import QAction, QActionGroup
|
from PySide6.QtGui import QAction, QActionGroup, QPixmap
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
|
QDialog,
|
||||||
|
QDialogButtonBox,
|
||||||
|
QHBoxLayout,
|
||||||
QInputDialog,
|
QInputDialog,
|
||||||
|
QLabel,
|
||||||
QLineEdit,
|
QLineEdit,
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
QMessageBox,
|
QMessageBox,
|
||||||
@@ -21,6 +25,7 @@ from PySide6.QtWidgets import (
|
|||||||
|
|
||||||
from .. import __version__, gitops
|
from .. import __version__, gitops
|
||||||
from ..config import Config, Game
|
from ..config import Config, Game
|
||||||
|
from ..paths import app_icon_path
|
||||||
from ..settings import load_settings, save_settings
|
from ..settings import load_settings, save_settings
|
||||||
from ..workers import CheckUpdatesWorker, DownloadWorker, RunWorker
|
from ..workers import CheckUpdatesWorker, DownloadWorker, RunWorker
|
||||||
from . import theme
|
from . import theme
|
||||||
@@ -257,13 +262,73 @@ class MainWindow(QMainWindow):
|
|||||||
help_menu.addAction(self.action_about)
|
help_menu.addAction(self.action_about)
|
||||||
|
|
||||||
def _show_about(self) -> None:
|
def _show_about(self) -> None:
|
||||||
QMessageBox.about(
|
"""Diàleg «Quant a» personalitzat: icona, nom gran i tot centrat."""
|
||||||
self,
|
dlg = QDialog(self)
|
||||||
f"Quant a {APP_NAME}",
|
dlg.setWindowTitle(f"Quant a {APP_NAME}")
|
||||||
f"<b>{APP_NAME}</b><br>"
|
dlg.setModal(True)
|
||||||
f"Versió {__version__}<br><br>"
|
|
||||||
"© 2026 JailDesigner",
|
lay = QVBoxLayout(dlg)
|
||||||
|
lay.setContentsMargins(40, 30, 40, 24)
|
||||||
|
lay.setSpacing(0)
|
||||||
|
|
||||||
|
# Logo (si el trobem); s'escala suau des del PNG gran.
|
||||||
|
icon_path = app_icon_path()
|
||||||
|
if icon_path is not None:
|
||||||
|
pix = QPixmap(str(icon_path))
|
||||||
|
if not pix.isNull():
|
||||||
|
logo = QLabel(alignment=Qt.AlignCenter)
|
||||||
|
logo.setPixmap(
|
||||||
|
pix.scaled(
|
||||||
|
96, 96, Qt.KeepAspectRatio, Qt.SmoothTransformation
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
lay.addWidget(logo)
|
||||||
|
lay.addSpacing(16)
|
||||||
|
|
||||||
|
# Nom de l'app: gran, en negreta i amb el morat de la marca.
|
||||||
|
name = QLabel(APP_NAME, alignment=Qt.AlignCenter)
|
||||||
|
nf = name.font()
|
||||||
|
nf.setPointSize(nf.pointSize() + 13)
|
||||||
|
nf.setBold(True)
|
||||||
|
name.setFont(nf)
|
||||||
|
name.setStyleSheet("color: #7c4dff;")
|
||||||
|
lay.addWidget(name)
|
||||||
|
lay.addSpacing(4)
|
||||||
|
|
||||||
|
# Versió en cursiva i atenuada.
|
||||||
|
ver = QLabel(f"Versió {__version__}", alignment=Qt.AlignCenter)
|
||||||
|
vf = ver.font()
|
||||||
|
vf.setItalic(True)
|
||||||
|
vf.setPointSize(vf.pointSize() + 1)
|
||||||
|
ver.setFont(vf)
|
||||||
|
ver.setStyleSheet("color: #8a8a8a;")
|
||||||
|
lay.addWidget(ver)
|
||||||
|
lay.addSpacing(18)
|
||||||
|
|
||||||
|
# Lema discret.
|
||||||
|
tag = QLabel("Clona, compila i juga · jailgames", alignment=Qt.AlignCenter)
|
||||||
|
tag.setStyleSheet("color: #8a8a8a;")
|
||||||
|
lay.addWidget(tag)
|
||||||
|
lay.addSpacing(14)
|
||||||
|
|
||||||
|
copy = QLabel("© 2026 JailDesigner", alignment=Qt.AlignCenter)
|
||||||
|
cf = copy.font()
|
||||||
|
cf.setPointSize(cf.pointSize() - 1)
|
||||||
|
copy.setFont(cf)
|
||||||
|
lay.addWidget(copy)
|
||||||
|
lay.addSpacing(24)
|
||||||
|
|
||||||
|
# Botó OK centrat.
|
||||||
|
buttons = QDialogButtonBox(QDialogButtonBox.Ok)
|
||||||
|
buttons.button(QDialogButtonBox.Ok).setText("D'acord")
|
||||||
|
buttons.accepted.connect(dlg.accept)
|
||||||
|
row = QHBoxLayout()
|
||||||
|
row.addStretch(1)
|
||||||
|
row.addWidget(buttons)
|
||||||
|
row.addStretch(1)
|
||||||
|
lay.addLayout(row)
|
||||||
|
|
||||||
|
dlg.exec()
|
||||||
|
|
||||||
def _build_theme_menu(self, parent_menu) -> None:
|
def _build_theme_menu(self, parent_menu) -> None:
|
||||||
"""Submenú Tema amb tres opcions exclusives: Sistema / Clar / Fosc."""
|
"""Submenú Tema amb tres opcions exclusives: Sistema / Clar / Fosc."""
|
||||||
|
|||||||
Reference in New Issue
Block a user