Files
Jackify/jackify/backend/handlers/ui_handler.py
Omni cd591c14e3 Initial public release v0.1.0 - Linux Wabbajack Modlist Application
Jackify provides native Linux support for Wabbajack modlist installation
   and management with automated Steam integration and Proton configuration.

   Key Features:
   - Almost Native Linux implementation (texconv.exe run via proton)
   - Automated Steam shortcut creation and Proton prefix management
   - Both CLI and GUI interfaces, with Steam Deck optimization

   Supported Games:
   - Skyrim Special Edition
   - Fallout 4
   - Fallout New Vegas
   - Oblivion, Starfield, Enderal, and diverse other games

   Technical Architecture:
   - Clean separation between frontend and backend services
   - Powered by jackify-engine 0.3.x for Wabbajack-matching modlist installation
2025-09-05 20:46:24 +01:00

180 lines
6.9 KiB
Python

"""
UIHandler module for managing user interface operations.
This module handles menus, prompts, and user interaction.
"""
import os
import logging
from typing import Optional, List, Dict, Tuple, Callable, Any
from pathlib import Path
class UIHandler:
def __init__(self):
self.logger = logging.getLogger(__name__)
def show_menu(self, title: str, options: List[Dict[str, Any]]) -> Optional[str]:
"""Display a menu and get user selection."""
try:
print(f"\n{title}")
print("=" * len(title))
for i, option in enumerate(options, 1):
print(f"{i}. {option['label']}")
while True:
try:
choice = input("\nEnter your choice (or 'q' to quit): ")
if choice.lower() == 'q':
return None
choice = int(choice)
if 1 <= choice <= len(options):
return options[choice - 1]['value']
else:
print("Invalid choice. Please try again.")
except ValueError:
print("Please enter a number.")
except Exception as e:
self.logger.error(f"Failed to show menu: {e}")
return None
def show_progress(self, message: str, total: int = 100) -> None:
"""Display a progress indicator."""
try:
print(f"\n{message}")
print("[" + " " * 50 + "] 0%", end="\r")
except Exception as e:
self.logger.error(f"Failed to show progress: {e}")
def update_progress(self, current: int, message: Optional[str] = None) -> None:
"""Update the progress indicator."""
try:
if message:
print(f"\n{message}")
progress = int(current / 2)
print("[" + "=" * progress + " " * (50 - progress) + f"] {current}%", end="\r")
except Exception as e:
self.logger.error(f"Failed to update progress: {e}")
def show_error(self, message: str, details: Optional[str] = None) -> None:
"""Display an error message."""
try:
print(f"\nError: {message}")
if details:
print(f"Details: {details}")
except Exception as e:
self.logger.error(f"Failed to show error: {e}")
def show_success(self, message: str, details: Optional[str] = None) -> None:
"""Display a success message."""
try:
print(f"\n✓ Success: {message}")
if details:
print(f"Details: {details}")
except Exception as e:
self.logger.error(f"Failed to show success: {e}")
def show_warning(self, message: str, details: Optional[str] = None) -> None:
"""Display a warning message."""
try:
print(f"\nWarning: {message}")
if details:
print(f"Details: {details}")
except Exception as e:
self.logger.error(f"Failed to show warning: {e}")
def get_input(self, prompt: str, default: Optional[str] = None) -> str:
"""Get user input with optional default value."""
try:
if default:
user_input = input(f"{prompt} [{default}]: ")
return user_input if user_input else default
return input(f"{prompt}: ")
except Exception as e:
self.logger.error(f"Failed to get input: {e}")
return ""
def get_confirmation(self, message: str, default: bool = True) -> bool:
"""Get user confirmation for an action."""
try:
default_str = "Y/n" if default else "y/N"
while True:
response = input(f"{message} [{default_str}]: ").lower()
if not response:
return default
if response in ['y', 'yes']:
return True
if response in ['n', 'no']:
return False
print("Please enter 'y' or 'n'.")
except Exception as e:
self.logger.error(f"Failed to get confirmation: {e}")
return default
def show_list(self, title: str, items: List[str], selectable: bool = True) -> Optional[str]:
"""Display a list of items, optionally selectable."""
try:
print(f"\n{title}")
print("=" * len(title))
for i, item in enumerate(items, 1):
print(f"{i}. {item}")
if selectable:
while True:
try:
choice = input("\nEnter your choice (or 'q' to quit): ")
if choice.lower() == 'q':
return None
choice = int(choice)
if 1 <= choice <= len(items):
return items[choice - 1]
else:
print("Invalid choice. Please try again.")
except ValueError:
print("Please enter a number.")
return None
except Exception as e:
self.logger.error(f"Failed to show list: {e}")
return None
def show_table(self, title: str, headers: List[str], rows: List[List[str]]) -> None:
"""Display data in a table format."""
try:
print(f"\n{title}")
print("=" * len(title))
# Calculate column widths
widths = [len(h) for h in headers]
for row in rows:
for i, cell in enumerate(row):
widths[i] = max(widths[i], len(str(cell)))
# Print headers
header_str = " | ".join(f"{h:<{w}}" for h, w in zip(headers, widths))
print(header_str)
print("-" * len(header_str))
# Print rows
for row in rows:
print(" | ".join(f"{str(cell):<{w}}" for cell, w in zip(row, widths)))
except Exception as e:
self.logger.error(f"Failed to show table: {e}")
def show_help(self, topic: str) -> None:
"""Display help information for a topic."""
try:
# This would typically load help content from a file or database
print(f"\nHelp: {topic}")
print("=" * (len(topic) + 6))
print("Help content would be displayed here.")
except Exception as e:
self.logger.error(f"Failed to show help: {e}")
def clear_screen(self) -> None:
"""Clear the terminal screen."""
try:
os.system('clear' if os.name == 'posix' else 'cls')
except Exception as e:
self.logger.error(f"Failed to clear screen: {e}")