Add Windows icon for PyInstaller executable

- Created create_icon.py script to generate network/discovery-themed icon
- Generated mbetter_discovery_icon.ico with multiple sizes (16x16 to 256x256)
- Updated Windows PyInstaller spec to use the icon
- Enhanced setup_discovery.py to automatically create icon during build
- Added icon preview PNG file for development reference

The icon features:
- Blue circular background with network theme
- Concentric radar circles representing discovery
- Signal waves for larger icon sizes
- Professional Windows executable appearance
parent 26dd76e0
#!/usr/bin/env python3
"""
Create an icon for MBetter Discovery application
Generates a .ico file for Windows PyInstaller builds
"""
try:
from PIL import Image, ImageDraw, ImageFont
import os
except ImportError:
print("Error: PIL (Pillow) is required but not installed.")
print("Please install it with: pip install Pillow")
exit(1)
def create_discovery_icon():
"""Create a discovery-themed icon"""
# Icon sizes for .ico file (Windows standard)
sizes = [16, 24, 32, 48, 64, 128, 256]
images = []
for size in sizes:
# Create image with transparent background
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
# Colors - network/discovery theme
bg_color = (41, 128, 185, 255) # Blue background
accent_color = (52, 152, 219, 255) # Lighter blue
white = (255, 255, 255, 255)
# Draw background circle
margin = max(1, size // 16)
circle_size = size - (margin * 2)
draw.ellipse([margin, margin, margin + circle_size, margin + circle_size],
fill=bg_color, outline=accent_color, width=max(1, size // 32))
# Draw network/radar pattern (concentric circles)
center = size // 2
if size >= 32:
# Multiple radar circles for larger icons
for i in range(3):
radius = (size // 6) + (i * size // 12)
if radius < center - margin:
draw.ellipse([center - radius, center - radius,
center + radius, center + radius],
outline=white, width=max(1, size // 64))
elif size >= 16:
# Single circle for smaller icons
radius = size // 4
draw.ellipse([center - radius, center - radius,
center + radius, center + radius],
outline=white, width=1)
# Draw center dot (discovery point)
dot_size = max(2, size // 16)
draw.ellipse([center - dot_size, center - dot_size,
center + dot_size, center + dot_size],
fill=white)
# Draw signal waves (for larger icons)
if size >= 48:
wave_length = size // 8
wave_width = max(1, size // 64)
# Top-right wave
start_x = center + size // 8
start_y = center - size // 8
draw.arc([start_x - wave_length, start_y - wave_length,
start_x + wave_length, start_y + wave_length],
225, 315, fill=white, width=wave_width)
# Bottom-right wave
start_x = center + size // 8
start_y = center + size // 8
draw.arc([start_x - wave_length, start_y - wave_length,
start_x + wave_length, start_y + wave_length],
135, 225, fill=white, width=wave_width)
images.append(img)
return images
def save_icon(images, filename):
"""Save images as .ico file"""
try:
# Save as .ico file with multiple sizes
images[0].save(filename, format='ICO',
sizes=[(img.width, img.height) for img in images])
print(f"✓ Icon saved as {filename}")
# Also save largest as PNG for preview
png_filename = filename.replace('.ico', '_preview.png')
images[-1].save(png_filename, format='PNG')
print(f"✓ Preview saved as {png_filename}")
return True
except Exception as e:
print(f"✗ Failed to save icon: {e}")
return False
def main():
"""Main function"""
print("Creating MBetter Discovery icon...")
try:
# Create icon images
images = create_discovery_icon()
# Save as .ico file
icon_filename = "mbetter_discovery_icon.ico"
if save_icon(images, icon_filename):
print(f"\n✓ Icon creation successful!")
print(f" Icon file: {icon_filename}")
print(f" Sizes included: {[img.size for img in images]}")
# Check file size
if os.path.exists(icon_filename):
file_size = os.path.getsize(icon_filename)
print(f" File size: {file_size} bytes")
return True
else:
return False
except Exception as e:
print(f"✗ Icon creation failed: {e}")
return False
if __name__ == "__main__":
success = main()
exit(0 if success else 1)
\ No newline at end of file
...@@ -54,5 +54,5 @@ exe = EXE( ...@@ -54,5 +54,5 @@ exe = EXE(
target_arch=None, target_arch=None,
codesign_identity=None, codesign_identity=None,
entitlements_file=None, entitlements_file=None,
icon=None, # Add path to .ico file if available icon='mbetter_discovery_icon.ico',
) )
\ No newline at end of file
...@@ -27,6 +27,32 @@ def install_requirements(): ...@@ -27,6 +27,32 @@ def install_requirements():
return True return True
def create_icon():
"""Create application icon"""
try:
print("Creating application icon...")
# Check if Pillow is available
try:
import PIL
print("✓ Pillow is available")
except ImportError:
print("Installing Pillow for icon creation...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "Pillow"])
# Run icon creation script
if os.path.exists("create_icon.py"):
subprocess.check_call([sys.executable, "create_icon.py"])
print("✓ Icon created successfully")
return True
else:
print("⚠ create_icon.py not found, skipping icon creation")
return True
except subprocess.CalledProcessError as e:
print(f"⚠ Icon creation failed: {e}")
return True # Don't fail the build if icon creation fails
def create_executable(): def create_executable():
"""Create executable using PyInstaller with spec files""" """Create executable using PyInstaller with spec files"""
try: try:
...@@ -35,6 +61,9 @@ def create_executable(): ...@@ -35,6 +61,9 @@ def create_executable():
print("Creating executable...") print("Creating executable...")
# Create icon first (especially important for Windows)
create_icon()
# Determine platform and spec file # Determine platform and spec file
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
spec_file = "mbetter_discovery_windows.spec" spec_file = "mbetter_discovery_windows.spec"
...@@ -63,6 +92,11 @@ def create_executable(): ...@@ -63,6 +92,11 @@ def create_executable():
if os.path.exists(exe_path): if os.path.exists(exe_path):
print(f"✓ Executable location: {exe_path}") print(f"✓ Executable location: {exe_path}")
# Show file size
file_size = os.path.getsize(exe_path)
size_mb = file_size / (1024 * 1024)
print(f" File size: {size_mb:.1f} MB")
return True return True
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment