#!/usr/bin/env python3 """Create system tray icons for DaemonControl. This script generates simple circular icons in three colors: - Green (active/running) - Gray (inactive/stopped) - Red (error) """ from pathlib import Path try: from PIL import Image, ImageDraw PIL_AVAILABLE = True except ImportError: PIL_AVAILABLE = False def create_icon_with_pil(color, filename, size=48): """Create icon using PIL/Pillow. Args: color: RGBA tuple (r, g, b, a) filename: Output filename size: Icon size in pixels """ # Create transparent background img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # Draw filled circle padding = 4 draw.ellipse( [padding, padding, size - padding, size - padding], fill=color, outline=(255, 255, 255, 180), width=2 ) # Save output_path = Path(__file__).parent / filename img.save(output_path) print(f" ✓ Created: {filename}") def create_icon_simple(color_name, filename, size=48): """Create simple PNG icon without PIL. Creates a minimal 48x48 PNG with a colored circle. Uses raw PNG format - basic but functional. Args: color_name: 'green', 'gray', or 'red' filename: Output filename size: Icon size (fixed at 48 for simplicity) """ # Simple PNG for basic colored square (fallback) # This is a very basic implementation # In production, PIL is recommended # Map color names to RGB colors = { 'green': (76, 175, 80), 'gray': (158, 158, 158), 'red': (244, 67, 54) } color = colors.get(color_name, (128, 128, 128)) # Create a simple solid color PNG # Note: This creates a square, not a circle, but works for basic functionality import struct import zlib width = height = size def create_png_data(): """Create raw PNG data.""" # PNG signature png_sig = b'\x89PNG\r\n\x1a\n' # IHDR chunk ihdr = struct.pack('>IIBBBBB', width, height, 8, 2, 0, 0, 0) ihdr_crc = zlib.crc32(b'IHDR' + ihdr) ihdr_chunk = struct.pack('>I', 13) + b'IHDR' + ihdr + struct.pack('>I', ihdr_crc) # IDAT chunk - image data # Simple solid color image raw_data = b'' for y in range(height): raw_data += b'\x00' # Filter type for x in range(width): # Draw circle dx = x - width // 2 dy = y - height // 2 dist = (dx * dx + dy * dy) ** 0.5 radius = width // 2 - 4 if dist <= radius: # Inside circle - use color raw_data += bytes(color) else: # Outside circle - transparent raw_data += b'\x00\x00\x00' compressed = zlib.compress(raw_data, 9) idat_crc = zlib.crc32(b'IDAT' + compressed) idat_chunk = struct.pack('>I', len(compressed)) + b'IDAT' + compressed + struct.pack('>I', idat_crc) # IEND chunk iend_crc = zlib.crc32(b'IEND') iend_chunk = struct.pack('>I', 0) + b'IEND' + struct.pack('>I', iend_crc) return png_sig + ihdr_chunk + idat_chunk + iend_chunk output_path = Path(__file__).parent / filename with open(output_path, 'wb') as f: f.write(create_png_data()) print(f" ✓ Created: {filename} (basic fallback)") def main(): """Create all three icons.""" print("=" * 60) print("Creating System Tray Icons for DaemonControl") print("=" * 60) print() if PIL_AVAILABLE: print("Using PIL/Pillow for high-quality icons...") print() # Green (running) - Material Design Green 500 create_icon_with_pil((76, 175, 80, 255), 'icon_active.png') # Gray (stopped) - Material Design Gray 500 create_icon_with_pil((158, 158, 158, 255), 'icon_inactive.png') # Red (error) - Material Design Red 500 create_icon_with_pil((244, 67, 54, 255), 'icon_error.png') else: print("⚠️ PIL/Pillow not available - using basic fallback") print(" Install Pillow for better quality icons:") print(" pip install Pillow") print() # Create simple fallback icons create_icon_simple('green', 'icon_active.png') create_icon_simple('gray', 'icon_inactive.png') create_icon_simple('red', 'icon_error.png') print() print("=" * 60) print("✅ All icons created successfully!") print("=" * 60) print() print(f"Icons location: {Path(__file__).parent}") print() print("Icon meanings:") print(" 🟢 icon_active.png - Daemon running") print(" ⚪ icon_inactive.png - Daemon stopped") print(" 🔴 icon_error.png - Daemon error") print() if __name__ == '__main__': main()