refactor settings handling to its own class

This commit is contained in:
Andrew Ward
2025-03-22 11:01:33 +00:00
parent 0f53b782b0
commit 900e2b9ef7
4 changed files with 130 additions and 67 deletions

View File

@@ -1,5 +1,6 @@
import tkinter as tk
from tkinter import ttk, messagebox
from utils.settings_manager import SettingsManager
class AIEditorManager:
"""
@@ -90,9 +91,9 @@ class AIEditorManager:
def save_settings(self, settings):
"""Save AI copy editing settings and update the UI"""
self.app.save_settings_to_JSON(settings)
SettingsManager.update_settings(settings)
messagebox.showinfo("Settings Updated", "Your settings have been saved successfully.")
self.app.load_settings() # Refresh settings if needed elsewhere
# Update the status indicator on the main screen with more specific information
self.update_status_display()

116
utils/settings_manager.py Normal file
View File

@@ -0,0 +1,116 @@
import json
import platform
from pathlib import Path
class SettingsManager:
"""
Centralizes access to application settings to prevent conflicts between components.
"""
@staticmethod
def get_settings_file_path(filename="settings.json"):
"""Get the platform-specific path for the settings file."""
if platform.system() == 'Darwin': # macOS
from utils.api_key_manager import APIKeyManager
mac_path = APIKeyManager.get_app_support_path_mac()
return f"{mac_path}/{filename}"
else:
return filename # Default to current directory for non-macOS systems
@classmethod
def get_default_settings(cls):
"""Return the default settings structure."""
return {
"chat_gpt_completion": False,
"model": "gpt-4o-mini",
"prompt": "",
"auto_apply_ai_to_recording": False,
"current_tone": "None",
"hide_banner": False,
"input_device": "Default",
"primary_device": "Select Device",
"secondary_device": "None",
"hotkeys": {
"record_start_stop": ["ctrl", "shift", "0"],
"stop_recording": ["ctrl", "shift", "9"],
"play_last_audio": ["ctrl", "shift", "8"],
"cancel_operation": ["ctrl", "shift", "1"]
},
"max_tokens": 750
}
@classmethod
def load_settings(cls):
"""Load settings from file, with defaults for missing values."""
settings_file = cls.get_settings_file_path()
default_settings = cls.get_default_settings()
try:
# Try to load existing settings
with open(settings_file, "r") as f:
settings = json.load(f)
# Check if settings need to be updated with new defaults
settings_updated = False
# Recursively update nested dictionaries with missing keys
def update_missing_settings(existing, defaults):
nonlocal settings_updated
for key, value in defaults.items():
if key not in existing:
existing[key] = value
settings_updated = True
elif isinstance(value, dict) and isinstance(existing[key], dict):
# Recursively update nested dictionaries
update_missing_settings(existing[key], value)
return existing
# Update settings with any missing values
settings = update_missing_settings(settings, default_settings)
# Save if any settings were updated
if settings_updated:
cls.save_settings(settings)
print("Settings file updated with new default values")
except FileNotFoundError:
# Create new settings file with defaults if it doesn't exist
settings = default_settings
cls.save_settings(settings)
return settings
@classmethod
def save_settings(cls, settings):
"""Save complete settings to file."""
settings_file = cls.get_settings_file_path()
with open(settings_file, "w") as f:
json.dump(settings, f)
@classmethod
def update_settings(cls, partial_settings):
"""
Update only specific settings without touching others.
Args:
partial_settings: Dictionary containing only the settings to update
"""
# First load existing settings
current_settings = cls.load_settings()
# Update settings (recursively for nested dictionaries)
def recursive_update(target, source):
for key, value in source.items():
if isinstance(value, dict) and key in target and isinstance(target[key], dict):
# If both are dictionaries, update recursively
recursive_update(target[key], value)
else:
# Otherwise just update the value
target[key] = value
recursive_update(current_settings, partial_settings)
# Save the updated settings
cls.save_settings(current_settings)
return current_settings

View File

@@ -25,6 +25,7 @@ from utils.resource_utils import ResourceUtils
from utils.tone_presets_manager import TonePresetsManager
from utils.presets_manager import PresetsManager
from utils.ai_editor_manager import AIEditorManager
from utils.settings_manager import SettingsManager
# Modify the load environment variables to load from config/.env
def load_env_file():
@@ -1168,75 +1169,20 @@ Please also make sure you read the Terms of use and licence statement before usi
print(f"Transcription error: An error occurred during transcription: {str(e)}")
def load_settings(self):
settings_file = self.get_settings_file_path("settings.json")
# Define default settings structure
default_settings = {
"chat_gpt_completion": False,
"model": self.default_model,
"prompt": "",
"auto_apply_ai_to_recording": False,
"current_tone": "None",
"hide_banner": False,
"input_device": "Default", # Add default for input device
"primary_device": "Select Device", # Also add for primary device
"secondary_device": "None", # Also add for secondary device
"hotkeys": {
"record_start_stop": ["ctrl", "shift", "0"],
"stop_recording": ["ctrl", "shift", "9"],
"play_last_audio": ["ctrl", "shift", "8"],
"cancel_operation": ["ctrl", "shift", "1"]
},
"max_tokens": 750
}
try:
# Try to load existing settings
with open(settings_file, "r") as f:
settings = json.load(f)
# Check if settings need to be updated with new defaults
settings_updated = False
# Recursively update nested dictionaries with missing keys
def update_missing_settings(existing, defaults):
nonlocal settings_updated
for key, value in defaults.items():
if key not in existing:
existing[key] = value
settings_updated = True
elif isinstance(value, dict) and isinstance(existing[key], dict):
# Recursively update nested dictionaries
update_missing_settings(existing[key], value)
return existing
# Update settings with any missing values
settings = update_missing_settings(settings, default_settings)
# Save if any settings were updated
if settings_updated:
self.save_settings_to_JSON(settings)
print("Settings file updated with new default values")
except FileNotFoundError:
# Create new settings file with defaults if it doesn't exist
settings = default_settings
self.save_settings_to_JSON(settings)
return settings
"""Load settings using the SettingsManager."""
return SettingsManager.load_settings()
def save_settings_to_JSON(self, settings):
settings_file = self.get_settings_file_path("settings.json")
with open(settings_file, "w") as f:
json.dump(settings, f)
"""Save complete settings using the SettingsManager."""
SettingsManager.save_settings(settings)
def update_settings(self, partial_settings):
"""Update specific settings without overwriting others."""
return SettingsManager.update_settings(partial_settings)
def get_settings_file_path(self, filename):
if platform.system() == 'Darwin': # Check if the OS is macOS
mac_path = APIKeyManager.get_app_support_path_mac()
return f"{mac_path}/{filename}"
else:
return filename # Default to current directory for non-macOS systems
"""Get the settings file path using SettingsManager."""
return SettingsManager.get_settings_file_path(filename)
# Methods for tone preset management
def show_tone_presets_manager(self):