Make the app icon work on macOS, Windows, and Linux.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
|
@ -46,7 +46,8 @@ endif()
|
||||||
# so MSVC needs mainCRTStartup as the entry point.
|
# so MSVC needs mainCRTStartup as the entry point.
|
||||||
file(GLOB MATURITA_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
file(GLOB MATURITA_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_executable(maturita WIN32 ${MATURITA_SOURCES})
|
add_executable(maturita WIN32 ${MATURITA_SOURCES}
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/maturita.rc")
|
||||||
else()
|
else()
|
||||||
add_executable(maturita ${MATURITA_SOURCES})
|
add_executable(maturita ${MATURITA_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -66,8 +67,8 @@ else()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The GTK stylesheet and window icon are loaded at runtime from the working
|
# The GTK stylesheet, window icon and Freedesktop share/ tree are loaded at
|
||||||
# directory (or next to the binary), so keep copies beside the built binary.
|
# runtime from the working directory (or next to the binary).
|
||||||
add_custom_command(TARGET maturita POST_BUILD
|
add_custom_command(TARGET maturita POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/style.css
|
${CMAKE_CURRENT_SOURCE_DIR}/style.css
|
||||||
|
|
@ -81,4 +82,7 @@ add_custom_command(TARGET maturita POST_BUILD
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/hicolor/512x512/apps
|
${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/hicolor/512x512/apps
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/app-icon.png
|
${CMAKE_CURRENT_SOURCE_DIR}/assets/app-icon.png
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/hicolor/512x512/apps/maturita.png)
|
${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/hicolor/512x512/apps/maturita.png
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/share
|
||||||
|
$<TARGET_FILE_DIR:maturita>/share)
|
||||||
|
|
|
||||||
17
Makefile
|
|
@ -17,12 +17,15 @@ GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk4)
|
||||||
CFLAGS = -Wall -Wextra -Wno-deprecated-declarations $(GTK_CFLAGS)
|
CFLAGS = -Wall -Wextra -Wno-deprecated-declarations $(GTK_CFLAGS)
|
||||||
LIBS = $(GTK_LIBS) -lm
|
LIBS = $(GTK_LIBS) -lm
|
||||||
|
|
||||||
# Windows (MSYS2 / MinGW): .exe suffix and no console window for the GUI.
|
# Windows (MSYS2 / MinGW): .exe suffix, no console window, embed .ico.
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
TARGET = maturita.exe
|
TARGET = maturita.exe
|
||||||
LIBS += -mwindows
|
LIBS += -mwindows
|
||||||
|
WINDRES ?= windres
|
||||||
|
RC_OBJ = maturita_rc.o
|
||||||
else
|
else
|
||||||
TARGET = maturita
|
TARGET = maturita
|
||||||
|
RC_OBJ =
|
||||||
# macOS Dock icon is set via AppKit (see macos_dock.c).
|
# macOS Dock icon is set via AppKit (see macos_dock.c).
|
||||||
ifeq ($(shell uname -s 2>/dev/null),Darwin)
|
ifeq ($(shell uname -s 2>/dev/null),Darwin)
|
||||||
LIBS += -framework AppKit -framework Foundation
|
LIBS += -framework AppKit -framework Foundation
|
||||||
|
|
@ -34,6 +37,7 @@ OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
ICON_SRC = assets/app-icon.png
|
ICON_SRC = assets/app-icon.png
|
||||||
ICON_DST = assets/icons/hicolor/512x512/apps/maturita.png
|
ICON_DST = assets/icons/hicolor/512x512/apps/maturita.png
|
||||||
|
ICON_ICO = assets/app-icon.ico
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
|
|
@ -41,11 +45,19 @@ $(ICON_DST): $(ICON_SRC)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
cp "$(ICON_SRC)" "$@"
|
cp "$(ICON_SRC)" "$@"
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
$(RC_OBJ): maturita.rc $(ICON_ICO)
|
||||||
|
$(WINDRES) maturita.rc -o $(RC_OBJ)
|
||||||
|
|
||||||
|
$(TARGET): $(SRC) $(ICON_DST) $(RC_OBJ)
|
||||||
|
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(RC_OBJ) $(LIBS)
|
||||||
|
else
|
||||||
$(TARGET): $(SRC) $(ICON_DST)
|
$(TARGET): $(SRC) $(ICON_DST)
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LIBS)
|
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGET) maturita.exe $(OBJ)
|
rm -f $(TARGET) maturita.exe $(OBJ) $(RC_OBJ) maturita_rc.o
|
||||||
|
|
||||||
run: $(TARGET)
|
run: $(TARGET)
|
||||||
./$(TARGET)
|
./$(TARGET)
|
||||||
|
|
@ -61,6 +73,7 @@ bundle: $(TARGET)
|
||||||
@cp style.css dist/
|
@cp style.css dist/
|
||||||
@mkdir -p dist/icons/hicolor/512x512/apps
|
@mkdir -p dist/icons/hicolor/512x512/apps
|
||||||
@cp "$(ICON_DST)" dist/icons/hicolor/512x512/apps/
|
@cp "$(ICON_DST)" dist/icons/hicolor/512x512/apps/
|
||||||
|
@cp -R share dist/
|
||||||
@ldd $(TARGET) | grep -Ei '/(ucrt64|mingw64)/bin/' | awk '{print $$3}' \
|
@ldd $(TARGET) | grep -Ei '/(ucrt64|mingw64)/bin/' | awk '{print $$3}' \
|
||||||
| xargs -r -I{} cp -f {} dist/
|
| xargs -r -I{} cp -f {} dist/
|
||||||
@echo "Bundled into dist/ - run dist/$(TARGET)"
|
@echo "Bundled into dist/ - run dist/$(TARGET)"
|
||||||
|
|
|
||||||
BIN
assets/app-icon.ico
Normal file
|
After Width: | Height: | Size: 75 KiB |
|
|
@ -1,5 +1,5 @@
|
||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal EnableExtensions
|
||||||
|
|
||||||
REM ---------------------------------------------------------------------------
|
REM ---------------------------------------------------------------------------
|
||||||
REM Native Windows build with MSVC. No MSYS2 or MinGW shell required.
|
REM Native Windows build with MSVC. No MSYS2 or MinGW shell required.
|
||||||
|
|
@ -67,10 +67,22 @@ if not defined GTK_CFLAGS (
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
REM --- 4. Compile -----------------------------------------------------------
|
if not exist "assets\app-icon.ico" (
|
||||||
|
echo [error] assets\app-icon.ico is missing.
|
||||||
|
echo Generate it with: python scripts\gen-icons.py
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM --- 4. Compile resources + sources ---------------------------------------
|
||||||
echo Building maturita.exe with MSVC...
|
echo Building maturita.exe with MSVC...
|
||||||
|
rc /nologo /fo maturita.res maturita.rc
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [error] Resource compile failed.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
cl /nologo /O2 /MD /W3 /std:c11 /D_CRT_SECURE_NO_WARNINGS ^
|
cl /nologo /O2 /MD /W3 /std:c11 /D_CRT_SECURE_NO_WARNINGS ^
|
||||||
%GTK_CFLAGS% maturita.c ^
|
%GTK_CFLAGS% *.c maturita.res ^
|
||||||
/Fe:maturita.exe ^
|
/Fe:maturita.exe ^
|
||||||
/link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup %GTK_LIBS%
|
/link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup %GTK_LIBS%
|
||||||
|
|
||||||
|
|
@ -79,7 +91,10 @@ if errorlevel 1 (
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not exist icons\hicolor\512x512\apps mkdir icons\hicolor\512x512\apps
|
||||||
|
copy /Y assets\app-icon.png icons\hicolor\512x512\apps\maturita.png >nul
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Built maturita.exe
|
echo Built maturita.exe ^(icon embedded from assets\app-icon.ico^)
|
||||||
echo Run it from this terminal with: maturita.exe
|
echo Run it from this terminal with: maturita.exe
|
||||||
echo Or use run-windows.bat / double-click maturita.exe.
|
echo Or use run-windows.bat / double-click maturita.exe.
|
||||||
|
|
|
||||||
97
main.c
|
|
@ -189,6 +189,7 @@ static const char *find_app_icon_file(void) {
|
||||||
static const char *paths[] = {
|
static const char *paths[] = {
|
||||||
ICON_FILE,
|
ICON_FILE,
|
||||||
ICON_THEME_DIR "/hicolor/512x512/apps/" ICON_NAME ".png",
|
ICON_THEME_DIR "/hicolor/512x512/apps/" ICON_NAME ".png",
|
||||||
|
SHARE_DIR "/icons/hicolor/512x512/apps/" ICON_NAME ".png",
|
||||||
ICON_FILE_ALT,
|
ICON_FILE_ALT,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
@ -201,12 +202,84 @@ static const char *find_app_icon_file(void) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GTK4 has no gtk_window_set_icon_from_file(); register a local hicolor
|
/* Kept alive for gdk_toplevel_set_icon_list() which does not take ownership. */
|
||||||
* theme dir and set the window icon by name instead. On macOS the Dock
|
static GList *app_icon_textures;
|
||||||
* tile ignores that, so also push the PNG through AppKit. */
|
|
||||||
|
static void clear_app_icon_textures(void) {
|
||||||
|
g_list_free_full(app_icon_textures, g_object_unref);
|
||||||
|
app_icon_textures = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* X11 / some compositors use the toplevel icon list for the taskbar tile. */
|
||||||
|
static void apply_toplevel_icon(GtkWindow *window) {
|
||||||
|
GdkSurface *surface;
|
||||||
|
const char *path;
|
||||||
|
GError *err = NULL;
|
||||||
|
GdkTexture *tex;
|
||||||
|
|
||||||
|
surface = gtk_native_get_surface(GTK_NATIVE(window));
|
||||||
|
if (!surface || !GDK_IS_TOPLEVEL(surface))
|
||||||
|
return;
|
||||||
|
|
||||||
|
path = find_app_icon_file();
|
||||||
|
if (!path)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tex = gdk_texture_new_from_filename(path, &err);
|
||||||
|
if (!tex) {
|
||||||
|
g_clear_error(&err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_app_icon_textures();
|
||||||
|
app_icon_textures = g_list_append(NULL, tex);
|
||||||
|
gdk_toplevel_set_icon_list(GDK_TOPLEVEL(surface), app_icon_textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_window_realize_icon(GtkWidget *widget, gpointer data) {
|
||||||
|
(void)data;
|
||||||
|
apply_toplevel_icon(GTK_WINDOW(widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepend ./share to XDG_DATA_DIRS so Wayland can find our .desktop file and
|
||||||
|
* hicolor icons without a system install (matches APP_ID). */
|
||||||
|
static void setup_portable_share_dir(void) {
|
||||||
|
char *abs;
|
||||||
|
const char *old;
|
||||||
|
char *neu;
|
||||||
|
|
||||||
|
if (!g_file_test(SHARE_DIR "/applications", G_FILE_TEST_IS_DIR) &&
|
||||||
|
!g_file_test(SHARE_DIR "/icons", G_FILE_TEST_IS_DIR))
|
||||||
|
return;
|
||||||
|
|
||||||
|
abs = g_canonicalize_filename(SHARE_DIR, NULL);
|
||||||
|
if (!abs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
old = g_getenv("XDG_DATA_DIRS");
|
||||||
|
if (old && old[0])
|
||||||
|
neu = g_strconcat(abs, G_SEARCHPATH_SEPARATOR_S, old, NULL);
|
||||||
|
else
|
||||||
|
neu = g_strconcat(abs,
|
||||||
|
G_SEARCHPATH_SEPARATOR_S "/usr/local/share"
|
||||||
|
G_SEARCHPATH_SEPARATOR_S "/usr/share",
|
||||||
|
NULL);
|
||||||
|
g_setenv("XDG_DATA_DIRS", neu, TRUE);
|
||||||
|
g_free(neu);
|
||||||
|
g_free(abs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register icon theme paths + window icon-name (Linux), AppKit Dock (macOS),
|
||||||
|
* and toplevel textures (X11 / fallbacks). Windows uses the .ico embedded
|
||||||
|
* via maturita.rc at link time. */
|
||||||
static void setup_window_icon(GtkWindow *window) {
|
static void setup_window_icon(GtkWindow *window) {
|
||||||
GtkIconTheme *theme;
|
GtkIconTheme *theme;
|
||||||
static const char *dirs[] = { ICON_THEME_DIR, ICON_THEME_DIR_ALT, NULL };
|
static const char *dirs[] = {
|
||||||
|
ICON_THEME_DIR,
|
||||||
|
ICON_THEME_DIR_ALT,
|
||||||
|
SHARE_DIR "/icons",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
const char *icon_file;
|
const char *icon_file;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -220,16 +293,21 @@ static void setup_window_icon(GtkWindow *window) {
|
||||||
gtk_window_set_default_icon_name(ICON_NAME);
|
gtk_window_set_default_icon_name(ICON_NAME);
|
||||||
gtk_window_set_icon_name(window, ICON_NAME);
|
gtk_window_set_icon_name(window, ICON_NAME);
|
||||||
} else {
|
} else {
|
||||||
g_warning("App icon '%s' not found (tried %s/ and %s/)",
|
g_warning("App icon '%s' not found (tried %s/, %s/, %s/icons/)",
|
||||||
ICON_NAME, ICON_THEME_DIR, ICON_THEME_DIR_ALT);
|
ICON_NAME, ICON_THEME_DIR, ICON_THEME_DIR_ALT, SHARE_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
icon_file = find_app_icon_file();
|
icon_file = find_app_icon_file();
|
||||||
if (icon_file)
|
if (icon_file)
|
||||||
macos_set_dock_icon(icon_file);
|
macos_set_dock_icon(icon_file);
|
||||||
|
#ifdef __APPLE__
|
||||||
else
|
else
|
||||||
g_warning("Dock icon PNG not found (tried %s and %s)",
|
g_warning("Dock icon PNG not found (tried %s and %s)",
|
||||||
ICON_FILE, ICON_FILE_ALT);
|
ICON_FILE, ICON_FILE_ALT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_signal_connect(window, "realize",
|
||||||
|
G_CALLBACK(on_window_realize_icon), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void activate(GtkApplication *app, gpointer user_data) {
|
void activate(GtkApplication *app, gpointer user_data) {
|
||||||
|
|
@ -398,9 +476,14 @@ int main(int argc, char **argv) {
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
app = gtk_application_new("org.example.maturita", G_APPLICATION_DEFAULT_FLAGS);
|
/* Must run before GtkApplication so Wayland can resolve our .desktop
|
||||||
|
* file / icons via the application id. */
|
||||||
|
setup_portable_share_dir();
|
||||||
|
|
||||||
|
app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
|
||||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||||
status = g_application_run(G_APPLICATION(app), argc, argv);
|
status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
clear_app_icon_textures();
|
||||||
g_object_unref(app);
|
g_object_unref(app);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,13 @@
|
||||||
#define HW_SUBJ 2 /* index of "Technické vybavení" */
|
#define HW_SUBJ 2 /* index of "Technické vybavení" */
|
||||||
#define CZ_SUBJ 3 /* index of "Český jazyk a literatura" */
|
#define CZ_SUBJ 3 /* index of "Český jazyk a literatura" */
|
||||||
#define CSS_FILE "style.css"
|
#define CSS_FILE "style.css"
|
||||||
|
#define APP_ID "org.maturita.Maturita"
|
||||||
#define ICON_NAME "maturita"
|
#define ICON_NAME "maturita"
|
||||||
#define ICON_FILE "assets/app-icon.png"
|
#define ICON_FILE "assets/app-icon.png"
|
||||||
#define ICON_THEME_DIR "assets/icons" /* cwd when run from source tree */
|
#define ICON_THEME_DIR "assets/icons" /* cwd when run from source tree */
|
||||||
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
||||||
#define ICON_FILE_ALT "icons/hicolor/512x512/apps/maturita.png"
|
#define ICON_FILE_ALT "icons/hicolor/512x512/apps/maturita.png"
|
||||||
|
#define SHARE_DIR "share" /* portable Freedesktop data root */
|
||||||
#define PROGRESS_DIR "progress"
|
#define PROGRESS_DIR "progress"
|
||||||
#define PROGRESS_U1 "progress/unit1.conf"
|
#define PROGRESS_U1 "progress/unit1.conf"
|
||||||
#define PROGRESS_U2 "progress/unit2.conf"
|
#define PROGRESS_U2 "progress/unit2.conf"
|
||||||
|
|
|
||||||
3
maturita.rc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/* Windows application icon embedded into maturita.exe.
|
||||||
|
* The first ICON resource becomes the Explorer / taskbar icon. */
|
||||||
|
1 ICON "assets/app-icon.ico"
|
||||||
85
scripts/gen-icons.py
Executable file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Regenerate assets/app-icon.ico and share/icons from assets/app-icon.png.
|
||||||
|
|
||||||
|
Uses macOS `sips` when available; otherwise requires Pillow.
|
||||||
|
Run from the repository root.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
SRC = ROOT / "assets" / "app-icon.png"
|
||||||
|
ICO = ROOT / "assets" / "app-icon.ico"
|
||||||
|
ICO_SIZES = [16, 32, 48, 64, 128, 256]
|
||||||
|
SHARE_SIZES = [16, 32, 48, 64, 128, 256, 512]
|
||||||
|
|
||||||
|
|
||||||
|
def resize_png(src: Path, dest: Path, size: int) -> None:
|
||||||
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
if subprocess.call(["which", "sips"], stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL) == 0:
|
||||||
|
subprocess.check_call(
|
||||||
|
["sips", "-z", str(size), str(size), str(src), "--out", str(dest)],
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
except ImportError as exc:
|
||||||
|
raise SystemExit(
|
||||||
|
"Need macOS sips or Pillow to resize icons"
|
||||||
|
) from exc
|
||||||
|
img = Image.open(src).convert("RGBA")
|
||||||
|
img = img.resize((size, size), Image.Resampling.LANCZOS)
|
||||||
|
img.save(dest, format="PNG")
|
||||||
|
|
||||||
|
|
||||||
|
def write_ico(entries: list[tuple[int, bytes]], dest: Path) -> None:
|
||||||
|
count = len(entries)
|
||||||
|
header = struct.pack("<HHH", 0, 1, count)
|
||||||
|
offset = 6 + 16 * count
|
||||||
|
direntries = []
|
||||||
|
blobs = []
|
||||||
|
for size, data in entries:
|
||||||
|
w = 0 if size >= 256 else size
|
||||||
|
h = 0 if size >= 256 else size
|
||||||
|
direntries.append(
|
||||||
|
struct.pack("<BBBBHHII", w, h, 0, 0, 1, 32, len(data), offset)
|
||||||
|
)
|
||||||
|
blobs.append(data)
|
||||||
|
offset += len(data)
|
||||||
|
dest.write_bytes(header + b"".join(direntries) + b"".join(blobs))
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if not SRC.is_file():
|
||||||
|
print(f"missing {SRC}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory(prefix="maturita-ico-") as tmp:
|
||||||
|
entries: list[tuple[int, bytes]] = []
|
||||||
|
for size in ICO_SIZES:
|
||||||
|
png = Path(tmp) / f"icon_{size}.png"
|
||||||
|
resize_png(SRC, png, size)
|
||||||
|
entries.append((size, png.read_bytes()))
|
||||||
|
write_ico(entries, ICO)
|
||||||
|
print(f"wrote {ICO.relative_to(ROOT)}")
|
||||||
|
|
||||||
|
for size in SHARE_SIZES:
|
||||||
|
dest = ROOT / "share" / "icons" / "hicolor" / f"{size}x{size}" / "apps" / "maturita.png"
|
||||||
|
resize_png(SRC, dest, size)
|
||||||
|
print(f"wrote {dest.relative_to(ROOT)}")
|
||||||
|
|
||||||
|
assets_icon = ROOT / "assets" / "icons" / "hicolor" / "512x512" / "apps" / "maturita.png"
|
||||||
|
resize_png(SRC, assets_icon, 512)
|
||||||
|
print(f"wrote {assets_icon.relative_to(ROOT)}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
14
share/applications/org.maturita.Maturita.desktop
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Version=1.0
|
||||||
|
Name=maturita.c
|
||||||
|
GenericName=Maturita study app
|
||||||
|
GenericName[cs]=Příprava na maturitu
|
||||||
|
Comment=Educational GTK app for maturita exam preparation
|
||||||
|
Comment[cs]=Vzdělávací GTK aplikace pro přípravu na maturitu
|
||||||
|
Exec=maturita
|
||||||
|
Icon=maturita
|
||||||
|
Terminal=false
|
||||||
|
Categories=Education;GTK;
|
||||||
|
StartupNotify=true
|
||||||
|
StartupWMClass=org.maturita.Maturita
|
||||||
BIN
share/icons/hicolor/128x128/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
share/icons/hicolor/16x16/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
share/icons/hicolor/256x256/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
share/icons/hicolor/32x32/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
share/icons/hicolor/48x48/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
share/icons/hicolor/512x512/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
share/icons/hicolor/64x64/apps/maturita.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |