Glossarion / splash_utils.py
Shirochi's picture
Upload 41 files
457b8fd verified
#splah_utils.py
import time
import atexit
class SplashManager:
"""Simple splash screen manager that works with main thread"""
def __init__(self):
self.splash_window = None
self._status_text = "Initializing..."
self.progress_value = 0 # Track actual progress 0-100
self.canvas_width = 320 # Progress bar dimensions (increased from 300)
self.canvas_height = 36 # Increased from 30
self._after_id = None
def start_splash(self):
"""Create splash window on main thread"""
try:
import tkinter as tk
print("🎨 Starting splash screen...")
# Create splash window on main thread
self.splash_window = tk.Tk()
self.splash_window.title("Loading Glossarion...")
self.splash_window.geometry("450x350")
self.splash_window.configure(bg='#2b2b2b')
self.splash_window.resizable(False, False)
self.splash_window.overrideredirect(True)
# Center the window
self.splash_window.update_idletasks()
x = (self.splash_window.winfo_screenwidth() // 2) - 225
y = (self.splash_window.winfo_screenheight() // 2) - 175
self.splash_window.geometry(f"450x350+{x}+{y}")
# Add content
main_frame = tk.Frame(self.splash_window, bg='#2b2b2b', relief='raised', bd=2)
main_frame.pack(fill='both', expand=True, padx=2, pady=2)
# Load the actual Halgakos.ico icon
self._load_icon(main_frame)
# Title
title_label = tk.Label(main_frame, text="Glossarion v4.8.5",
bg='#2b2b2b', fg='#4a9eff', font=('Arial', 20, 'bold'))
title_label.pack(pady=(10, 5))
# Subtitle
subtitle_label = tk.Label(main_frame, text="Advanced AI Translation Suite",
bg='#2b2b2b', fg='#cccccc', font=('Arial', 12))
subtitle_label.pack(pady=(0, 15))
# Status
self.status_label = tk.Label(main_frame, text=self._status_text,
bg='#2b2b2b', fg='#ffffff', font=('Arial', 11))
self.status_label.pack(pady=(10, 10))
# Progress bar container
progress_frame = tk.Frame(main_frame, bg='#2b2b2b')
progress_frame.pack(pady=(5, 15)) # Adjusted padding for larger bar
# Progress bar background
self.progress_bg = tk.Canvas(progress_frame, width=self.canvas_width, height=self.canvas_height,
bg='#2b2b2b', highlightthickness=0)
self.progress_bg.pack()
# Create border
self.progress_bg.create_rectangle(1, 1, self.canvas_width-1, self.canvas_height-1,
outline='#666666', width=2)
# Create background
self.progress_bg.create_rectangle(3, 3, self.canvas_width-3, self.canvas_height-3,
fill='#1a1a1a', outline='')
# Progress bar fill (will be updated)
self.progress_fill = None
# Progress percentage text - moved up and with better font
text_x = self.canvas_width // 2 # 160 for 320px width
text_y = 13.5 # Positioned slightly above center for visual balance
# Use a cleaner, more modern font
progress_font = ('Montserrat', 12, 'bold') # Increased size to 12
# Create outline for better readability
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx != 0 or dy != 0:
self.progress_bg.create_text(text_x + dx, text_y + dy, text="0%",
fill='#000000', font=progress_font,
tags="outline", anchor='center')
# Main text on top (white)
self.progress_text = self.progress_bg.create_text(text_x, text_y, text="0%",
fill='#ffffff', font=progress_font,
anchor='center')
# Version info
version_label = tk.Label(main_frame, text="Starting up...",
bg='#2b2b2b', fg='#888888', font=('Arial', 9))
version_label.pack(side='bottom', pady=(0, 15))
# Start progress animation
self._animate_progress()
# Update the display
self.splash_window.update()
# Register cleanup
atexit.register(self.close_splash)
return True
except Exception as e:
print(f"⚠️ Could not start splash: {e}")
return False
def _load_icon(self, parent):
"""Load the Halgakos.ico icon"""
try:
# Get icon path - handle both development and packaged modes
import os
import sys
import tkinter as tk
if getattr(sys, 'frozen', False):
# Running as .exe
base_dir = sys._MEIPASS
else:
# Running as .py files
base_dir = os.path.dirname(os.path.abspath(__file__))
ico_path = os.path.join(base_dir, 'Halgakos.ico')
if os.path.isfile(ico_path):
try:
# Try PIL first for better quality
from PIL import Image, ImageTk
pil_image = Image.open(ico_path)
pil_image = pil_image.resize((128, 128), Image.Resampling.LANCZOS)
icon_photo = ImageTk.PhotoImage(pil_image, master=self.splash_window)
icon_label = tk.Label(parent, image=icon_photo, bg='#2b2b2b')
icon_label.image = icon_photo # Keep reference
icon_label.pack(pady=(20, 10))
return
except ImportError:
# Fallback to basic tkinter
try:
icon_image = tk.PhotoImage(file=ico_path)
icon_label = tk.Label(parent, image=icon_image, bg='#2b2b2b')
icon_label.image = icon_image
icon_label.pack(pady=(20, 10))
return
except tk.TclError:
pass
except Exception:
pass
# Fallback emoji if icon loading fails
import tkinter as tk
icon_frame = tk.Frame(parent, bg='#4a9eff', width=128, height=128)
icon_frame.pack(pady=(20, 10))
icon_frame.pack_propagate(False)
icon_label = tk.Label(icon_frame, text="📚", font=('Arial', 64),
bg='#4a9eff', fg='white')
icon_label.pack(expand=True)
def _animate_progress(self):
"""Animate progress bar filling up"""
# Cancel any existing after callback first
if self._after_id:
try:
self.splash_window.after_cancel(self._after_id)
except:
pass
self._after_id = None
if self.splash_window and self.splash_window.winfo_exists():
try:
# Auto-increment progress for visual effect during startup
if self.progress_value < 100:
# Increment at different rates for different phases
if self.progress_value < 30:
self.progress_value += 8 # Fast initial progress
elif self.progress_value < 70:
self.progress_value += 4 # Medium progress
elif self.progress_value < 90:
self.progress_value += 2 # Slow progress
else:
self.progress_value += 1 # Very slow final progress
# Cap at 99% until explicitly set to 100%
if self.progress_value >= 99:
self.progress_value = 99
# Update progress bar fill
if self.progress_fill:
self.progress_bg.delete(self.progress_fill)
# Also delete old highlight
self.progress_bg.delete("highlight")
# Calculate fill width (3 to canvas_width-3)
fill_width = int((self.progress_value / 100) * (self.canvas_width - 6)) # -6 for borders
if fill_width > 0:
# Create gradient effect
self.progress_fill = self.progress_bg.create_rectangle(
3, 3, 3 + fill_width, self.canvas_height - 3,
fill='#4a9eff', outline=''
)
# Add a highlight effect (adjusted for new height)
if fill_width > 10:
self.progress_bg.create_rectangle(
3, 3, min(13, 3 + fill_width), 12,
fill='#6bb6ff', outline='', tags="highlight"
)
# Update percentage text without changing position
percent_text = f"{self.progress_value}%"
# Update main text
self.progress_bg.itemconfig(self.progress_text, text=percent_text)
# Update all outline layers
for item in self.progress_bg.find_withtag("outline"):
self.progress_bg.itemconfig(item, text=percent_text)
# Ensure text stays on top of progress fill
self.progress_bg.tag_raise("outline")
self.progress_bg.tag_raise(self.progress_text)
# Store the after ID so we can cancel it later
self._after_id = self.splash_window.after(100, self._animate_progress)
except Exception:
self._after_id = None
pass
def update_status(self, message):
"""Update splash status and progress with enhanced module loading support"""
self._status_text = message
try:
if self.splash_window and hasattr(self, 'status_label'):
self.status_label.config(text=message)
# Enhanced progress mapping starting module loading at 10%
progress_map = {
"Loading theme framework...": 5,
"Loading UI framework...": 8,
# Module loading phase - starts at 10% and goes to 85%
"Loading translation modules...": 10,
"Initializing module system...": 15,
"Loading translation engine...": 20,
"Validating translation engine...": 30,
"✅ translation engine loaded": 40,
"Loading glossary extractor...": 45,
"Validating glossary extractor...": 55,
"✅ glossary extractor loaded": 65,
"Loading EPUB converter...": 70,
"✅ EPUB converter loaded": 75,
"Loading QA scanner...": 78,
"✅ QA scanner loaded": 82,
"Finalizing module initialization...": 85,
"✅ All modules loaded successfully": 88,
"Creating main window...": 92,
"Ready!": 100
}
# Check for exact matches first
if message in progress_map:
self.set_progress(progress_map[message])
else:
# Check for partial matches
for key, value in progress_map.items():
if key in message:
self.set_progress(value)
break
self.splash_window.update()
except:
pass
def set_progress(self, value):
"""Manually set progress value (0-100)"""
self.progress_value = max(0, min(100, value))
def close_splash(self):
"""Close the splash screen with proper text visibility"""
try:
# IMPORTANT: Cancel the animation first
if self._after_id and self.splash_window:
try:
self.splash_window.after_cancel(self._after_id)
except:
pass
self._after_id = None
if self.splash_window and self.splash_window.winfo_exists():
# Set to 100% and ensure text is visible
self.progress_value = 100
# Update display one last time without scheduling another callback
if hasattr(self, 'progress_fill') and self.progress_fill:
self.progress_bg.delete(self.progress_fill)
self.progress_bg.delete("highlight")
# Create the 100% progress bar (but leave space for text)
fill_width = int((self.progress_value / 100) * (self.canvas_width - 6))
if fill_width > 0:
# Create progress fill that doesn't cover the text area
self.progress_fill = self.progress_bg.create_rectangle(
3, 3, 3 + fill_width, self.canvas_height - 3,
fill='#4a9eff', outline=''
)
# Add highlight effect
if fill_width > 10:
self.progress_bg.create_rectangle(
3, 3, min(13, 3 + fill_width), 12,
fill='#6bb6ff', outline='', tags="highlight"
)
# CRITICAL: Make sure text stays on top and is visible
if hasattr(self, 'progress_text'):
self.progress_bg.itemconfig(self.progress_text, text="100%", fill='#ffffff')
# Update all outline layers for better visibility
for item in self.progress_bg.find_withtag("outline"):
self.progress_bg.itemconfig(item, text="100%", fill='#000000')
# Ensure text layers are on top of progress fill
self.progress_bg.tag_raise("outline")
if hasattr(self, 'progress_text'):
self.progress_bg.tag_raise(self.progress_text)
self.splash_window.update()
time.sleep(0.1)
self.splash_window.destroy()
self.splash_window = None
except:
# Ensure cleanup even on error
self._after_id = None
self.splash_window = None