Added App Icon
This commit is contained in:
@@ -13,6 +13,7 @@ Install Python 3.11+ with the Python launcher, then run:
|
||||
```
|
||||
|
||||
The script creates a virtual environment and installs dependencies automatically.
|
||||
On first launch, it also adds a **SUB Control** desktop shortcut.
|
||||
Select a COM port and **Connect**, or choose **Demo Mode** to try it without hardware.
|
||||
Connection settings are under **•••**.
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,14 @@
|
||||
"""Package the original PNG in a Windows ICO without altering its pixels."""
|
||||
from pathlib import Path
|
||||
import struct
|
||||
|
||||
root = Path(__file__).resolve().parent
|
||||
png = (root / "assets" / "sub-control-icon.png").read_bytes()
|
||||
if png[:8] != b"\x89PNG\r\n\x1a\n":
|
||||
raise ValueError("Icon source must be PNG")
|
||||
width, height = struct.unpack(">II", png[16:24])
|
||||
if not (1 <= width <= 256 and 1 <= height <= 256):
|
||||
raise ValueError("Windows icon source must be at most 256 x 256")
|
||||
header = struct.pack("<HHH", 0, 1, 1)
|
||||
entry = struct.pack("<BBBBHHII", width % 256, height % 256, 0, 0, 1, 32, len(png), 22)
|
||||
(root / "assets" / "sub-control.ico").write_bytes(header + entry + png)
|
||||
@@ -0,0 +1,43 @@
|
||||
param([switch]$UpdateIcon)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$shortcutProject = $PSScriptRoot
|
||||
$shortcutMarker = Join-Path $shortcutProject 'runtime\desktop-shortcut-created.txt'
|
||||
if ((Test-Path -LiteralPath $shortcutMarker) -and -not $UpdateIcon) { return }
|
||||
|
||||
try {
|
||||
# Resolves the real Desktop, including a redirected/OneDrive Desktop.
|
||||
$shortcutDesktop = [Environment]::GetFolderPath('DesktopDirectory')
|
||||
if (-not $shortcutDesktop) { throw 'Windows Desktop folder is unavailable.' }
|
||||
$shortcutPath = Join-Path $shortcutDesktop 'SUB Control.lnk'
|
||||
|
||||
# Never replace a shortcut the user already has.
|
||||
if (-not (Test-Path -LiteralPath $shortcutPath)) {
|
||||
$shortcutShell = New-Object -ComObject WScript.Shell
|
||||
$shortcutLink = $shortcutShell.CreateShortcut($shortcutPath)
|
||||
$shortcutLink.TargetPath = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe'
|
||||
$shortcutLink.Arguments = '-NoProfile -WindowStyle Hidden -File "' + (Join-Path $shortcutProject 'run.ps1') + '"'
|
||||
$shortcutLink.WorkingDirectory = $shortcutProject
|
||||
$shortcutLink.Description = 'Launch SUB Control'
|
||||
$shortcutLink.WindowStyle = 7
|
||||
$shortcutIcon = Join-Path $shortcutProject 'assets\sub-control.ico'
|
||||
if (Test-Path -LiteralPath $shortcutIcon) { $shortcutLink.IconLocation = "$shortcutIcon,0" }
|
||||
$shortcutLink.Save()
|
||||
} elseif ($UpdateIcon) {
|
||||
$shortcutShell = New-Object -ComObject WScript.Shell
|
||||
$shortcutLink = $shortcutShell.CreateShortcut($shortcutPath)
|
||||
$expectedScript = '"' + (Join-Path $shortcutProject 'run.ps1') + '"'
|
||||
if ($shortcutLink.Arguments.Contains($expectedScript)) {
|
||||
$shortcutLink.IconLocation = (Join-Path $shortcutProject 'assets\sub-control.ico') + ',0'
|
||||
$shortcutLink.Save()
|
||||
} else {
|
||||
throw 'Existing shortcut belongs to another installation; left unchanged.'
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Path (Split-Path -Parent $shortcutMarker) -Force | Out-Null
|
||||
Set-Content -LiteralPath $shortcutMarker -Value $shortcutPath
|
||||
} catch {
|
||||
# Desktop permissions must not prevent the controller from starting.
|
||||
Write-Warning "Could not create the SUB Control desktop shortcut: $_"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
"""Best-effort Windows first-run shortcut, including direct Python launches."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
|
||||
def ensure_desktop_shortcut():
|
||||
if os.name != "nt":
|
||||
return
|
||||
root = Path(__file__).resolve().parent
|
||||
if (root / "runtime" / "desktop-shortcut-created.txt").exists():
|
||||
return
|
||||
powershell = Path(os.environ["SystemRoot"]) / "System32/WindowsPowerShell/v1.0/powershell.exe"
|
||||
try:
|
||||
subprocess.run(
|
||||
[str(powershell), "-NoProfile", "-NonInteractive", "-File", str(root / "create_shortcut.ps1")],
|
||||
cwd=root, timeout=10, check=True, capture_output=True,
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
)
|
||||
except (OSError, subprocess.SubprocessError) as error:
|
||||
print(f"Desktop shortcut setup skipped: {error}")
|
||||
@@ -3,6 +3,8 @@ $ErrorActionPreference = "Stop"
|
||||
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Set-Location -LiteralPath $projectRoot
|
||||
|
||||
& (Join-Path $projectRoot 'create_shortcut.ps1')
|
||||
|
||||
if (-not (Get-Command py -ErrorAction SilentlyContinue)) {
|
||||
throw "Python 3.11 or newer is required. Install Python from python.org, then run this script again."
|
||||
}
|
||||
|
||||
@@ -585,6 +585,12 @@ def start_local_server(directory: Path) -> int:
|
||||
|
||||
|
||||
def main():
|
||||
if os.name == "nt":
|
||||
# Keep the running window separate from generic Python taskbar groups.
|
||||
import ctypes
|
||||
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("SUBControl.Desktop")
|
||||
from desktop_shortcut import ensure_desktop_shortcut
|
||||
ensure_desktop_shortcut()
|
||||
api = ControlApi()
|
||||
api._migrate_legacy_model()
|
||||
project_root = Path(__file__).resolve().parent
|
||||
@@ -602,7 +608,8 @@ def main():
|
||||
window.events.maximized += lambda: setattr(api, "maximized", True)
|
||||
window.events.restored += lambda: setattr(api, "maximized", False)
|
||||
try:
|
||||
webview.start(debug=True)
|
||||
icon_path = project_root / "assets" / "sub-control.ico"
|
||||
webview.start(debug=True, icon=str(icon_path) if icon_path.is_file() else None)
|
||||
finally:
|
||||
api.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user