Use the new app icon
The icon now comes from images/mtga-assistant-icon.png: make_icon.py copies it into the package (window, taskbar and tray icon) and builds the Windows .ico used for the .exe. The old generated SVG icon is gone. The PyInstaller spec also keeps QtNetwork, needed for single-instance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c4533d12c0
commit
fb6220155c
7 files changed
+23
-33
No files matched your search
+22
-20
@@ -1,39 +1,41 @@
|
||||
"""Render assets/icon.svg to assets/icon.ico (PNG-compressed entries at the usual Windows sizes).
|
||||
"""Build the app icons from images/mtga-assistant-icon.png (the single source image).
|
||||
|
||||
Run with: uv run python packaging/make_icon.py
|
||||
Writes:
|
||||
* src/mtga_assistant/icon.png: loaded at runtime for the window, taskbar and tray icon.
|
||||
* images/mtga-assistant-icon.ico: the Windows .exe icon (PNG-compressed entries at the usual sizes).
|
||||
|
||||
Run after changing the source image: uv run python packaging/make_icon.py
|
||||
"""
|
||||
|
||||
import shutil
|
||||
import struct
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import QBuffer, QByteArray, QIODevice, Qt
|
||||
from PySide6.QtGui import QGuiApplication, QImage, QPainter
|
||||
from PySide6.QtSvg import QSvgRenderer
|
||||
from PySide6.QtGui import QGuiApplication, QImage
|
||||
|
||||
SIZES = [16, 24, 32, 48, 64, 128, 256]
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
SOURCE = ROOT / "images" / "mtga-assistant-icon.png"
|
||||
|
||||
|
||||
def render_png(renderer: QSvgRenderer, size: int) -> bytes:
|
||||
img = QImage(size, size, QImage.Format.Format_ARGB32)
|
||||
img.fill(Qt.GlobalColor.transparent)
|
||||
painter = QPainter(img)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
renderer.render(painter)
|
||||
painter.end()
|
||||
def png_at(img: QImage, size: int) -> bytes:
|
||||
scaled = img.scaled(size, size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
|
||||
data = QByteArray()
|
||||
buf = QBuffer(data)
|
||||
buf.open(QIODevice.OpenModeFlag.WriteOnly)
|
||||
img.save(buf, "PNG")
|
||||
return bytes(data)
|
||||
scaled.save(buf, "PNG") # type: ignore[arg-type] # PySide accepts str; its stubs say bytes
|
||||
return data.data()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
QGuiApplication(sys.argv[:1])
|
||||
renderer = QSvgRenderer(str(ROOT / "assets/icon.svg"))
|
||||
pngs = [(size, render_png(renderer, size)) for size in SIZES]
|
||||
# ICONDIR header, then one ICONDIRENTRY per image, then the PNG data.
|
||||
img = QImage(str(SOURCE))
|
||||
if img.isNull():
|
||||
sys.exit(f"can't read {SOURCE}")
|
||||
pngs = [(size, png_at(img, size)) for size in SIZES]
|
||||
# ICONDIR header, one ICONDIRENTRY per image, then the PNG data.
|
||||
out = struct.pack("<HHH", 0, 1, len(pngs))
|
||||
offset = 6 + 16 * len(pngs)
|
||||
for size, png in pngs:
|
||||
@@ -41,10 +43,10 @@ def main() -> None:
|
||||
out += struct.pack("<BBBBHHII", dim, dim, 0, 0, 1, 32, len(png), offset)
|
||||
offset += len(png)
|
||||
out += b"".join(png for _, png in pngs)
|
||||
(ROOT / "assets/icon.ico").write_bytes(out)
|
||||
# The app loads this at runtime (window/taskbar icon), so it lives inside the package.
|
||||
(ROOT / "src/mtga_assistant/icon.png").write_bytes(dict(pngs)[256])
|
||||
print(f"wrote assets/icon.ico ({len(out)} bytes) and src/mtga_assistant/icon.png")
|
||||
ico = SOURCE.with_suffix(".ico")
|
||||
ico.write_bytes(out)
|
||||
shutil.copyfile(SOURCE, ROOT / "src" / "mtga_assistant" / "icon.png")
|
||||
print(f"wrote {ico.relative_to(ROOT)} and src/mtga_assistant/icon.png from {SOURCE.relative_to(ROOT)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user