import os import json import subprocess from datetime import datetime from pathlib import Path import uuid class ProfileManager: def __init__(self): self.config_dir = Path.home() / ".local/share/plasma-display-profiles" self.config_dir.mkdir(parents=True, exist_ok=True) self.metadata_file = self.config_dir / "profiles.json" self.script_path = self.find_script() # Initialize metadata file if it doesn't exist if not self.metadata_file.exists(): self.save_metadata([]) def find_script(self): """Find the bash script for display management""" # Check common locations possible_paths = [ Path(__file__).parent.parent / "scripts/display-script.sh", Path.home() / "bin/display-script.sh", Path("/usr/local/bin/display-script.sh"), ] for path in possible_paths: if path.exists(): return path # For now, return None - we'll handle this gracefully return None def load_metadata(self): """Load profile metadata from JSON file""" try: with open(self.metadata_file, 'r') as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError): return [] def save_metadata(self, profiles): """Save profile metadata to JSON file""" with open(self.metadata_file, 'w') as f: json.dump(profiles, f, indent=2) def list_profiles(self): """Return list of all profiles""" return self.load_metadata() def save_profile(self, name): """Save current display configuration as a new profile""" profiles = self.load_metadata() # Generate unique ID profile_id = str(uuid.uuid4()) timestamp = datetime.now().isoformat() # Create profile entry profile = { 'id': profile_id, 'name': name, 'created': timestamp, 'modified': timestamp, 'script_file': f"{profile_id}.sh", 'shortcut': None } # TODO: Call bash script to save display configuration # For now, create a placeholder script file script_file = self.config_dir / profile['script_file'] script_file.write_text(f"#!/bin/bash\n# Display profile: {name}\n# Created: {timestamp}\n") script_file.chmod(0o755) # If script exists, call it if self.script_path and self.script_path.exists(): try: subprocess.run([str(self.script_path), 'save', str(script_file)], check=True, capture_output=True) except subprocess.CalledProcessError as e: raise Exception(f"Script execution failed: {e.stderr.decode()}") profiles.append(profile) self.save_metadata(profiles) def load_profile(self, profile_id): """Load a display profile""" profiles = self.load_metadata() profile = next((p for p in profiles if p['id'] == profile_id), None) if not profile: raise Exception(f"Profile not found: {profile_id}") script_file = self.config_dir / profile['script_file'] if not script_file.exists(): raise Exception(f"Profile script not found: {script_file}") # Execute the profile script try: if self.script_path and self.script_path.exists(): subprocess.run([str(self.script_path), 'load', str(script_file)], check=True, capture_output=True) else: # Fallback: execute script directly subprocess.run([str(script_file)], check=True, capture_output=True) except subprocess.CalledProcessError as e: raise Exception(f"Failed to load profile: {e.stderr.decode()}") def delete_profile(self, profile_id): """Delete a profile""" profiles = self.load_metadata() profile = next((p for p in profiles if p['id'] == profile_id), None) if not profile: raise Exception(f"Profile not found: {profile_id}") # Remove script file script_file = self.config_dir / profile['script_file'] if script_file.exists(): script_file.unlink() # Remove from metadata profiles = [p for p in profiles if p['id'] != profile_id] self.save_metadata(profiles) def rename_profile(self, profile_id, new_name): """Rename a profile""" profiles = self.load_metadata() profile = next((p for p in profiles if p['id'] == profile_id), None) if not profile: raise Exception(f"Profile not found: {profile_id}") profile['name'] = new_name profile['modified'] = datetime.now().isoformat() self.save_metadata(profiles)