Update db_manager.py

This commit is contained in:
2026-01-03 16:16:05 +01:00
committed by GitHub
parent 29335bd4d5
commit 5f3f8e2076

View File

@@ -1,111 +1,170 @@
import sqlite3 import sqlite3
import json import json
import os import os
from pathlib import Path
from datetime import datetime from datetime import datetime
DB_FILE = "app_data.db" class DatabaseManager:
JSON_BACKUP = "settings.json" # The old file you want to import from def __init__(self, db_path="app_data.db"):
self.db_path = db_path
self.conn = None
self.connect()
self.init_tables()
def get_db_connection(): def connect(self):
conn = sqlite3.connect(DB_FILE) self.conn = sqlite3.connect(self.db_path, check_same_thread=False)
conn.row_factory = sqlite3.Row # Allows accessing columns by name self.conn.row_factory = sqlite3.Row
return conn
def init_db(): def init_tables(self):
"""Creates tables and imports JSON if DB is new.""" """Create tables for App Config, Project Settings, and Snippets."""
conn = get_db_connection() cursor = self.conn.cursor()
cursor = conn.cursor()
# 1. Create Settings Table (Keyed by Path) # 1. Project Settings (Replaces your per-file JSONs)
cursor.execute(''' cursor.execute('''
CREATE TABLE IF NOT EXISTS settings ( CREATE TABLE IF NOT EXISTS projects (
path TEXT PRIMARY KEY, path TEXT PRIMARY KEY,
params TEXT, parent_dir TEXT,
filename TEXT,
data TEXT,
is_batch INTEGER,
updated_at TIMESTAMP updated_at TIMESTAMP
) )
''') ''')
# 2. Create Batch History Table # 2. Global App Config (Replaces config.json)
cursor.execute(''' cursor.execute('''
CREATE TABLE IF NOT EXISTS batch_log ( CREATE TABLE IF NOT EXISTS app_config (
id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT PRIMARY KEY,
timestamp TEXT, value TEXT
path TEXT,
status TEXT,
details TEXT
) )
''') ''')
# 3. Check for Migration (If DB is empty but JSON exists) # 3. Snippets (Replaces snippets.json)
cursor.execute('SELECT count(*) FROM settings') cursor.execute('''
count = cursor.fetchone()[0] CREATE TABLE IF NOT EXISTS snippets (
name TEXT PRIMARY KEY,
if count == 0 and os.path.exists(JSON_BACKUP): content TEXT
print(f"Migration: Database empty. Importing from {JSON_BACKUP}...")
try:
with open(JSON_BACKUP, 'r') as f:
data = json.load(f)
# Assumes JSON structure: {"/path/to/img1": {config}, "/path/to/img2": {config}}
for path, config in data.items():
cursor.execute(
'INSERT OR REPLACE INTO settings (path, params, updated_at) VALUES (?, ?, ?)',
(path, json.dumps(config), datetime.now())
) )
conn.commit() ''')
print("Migration successful.") self.conn.commit()
# --- MIGRATION LOGIC ---
def is_empty(self):
cursor = self.conn.cursor()
cursor.execute("SELECT COUNT(*) FROM projects")
return cursor.fetchone()[0] == 0
def migrate_from_json(self, root_dir):
"""Scans folder for .json files and imports them if DB is empty."""
print("Starting Migration from JSON...")
root = Path(root_dir)
count = 0
# 1. Migrate Projects
for json_file in root.glob("*.json"):
if json_file.name in [".editor_config.json", ".editor_snippets.json"]:
continue
try:
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
is_batch = 1 if "batch_data" in data or isinstance(data, list) else 0
self.save_project(json_file, data, is_batch)
count += 1
except Exception as e: except Exception as e:
print(f"Migration failed: {e}") print(f"Failed to migrate {json_file}: {e}")
conn.commit() # 2. Migrate Config
conn.close() config_path = root / ".editor_config.json"
if config_path.exists():
with open(config_path, 'r') as f:
self.save_app_config(json.load(f))
# --- SETTINGS FUNCTIONS --- # 3. Migrate Snippets
snip_path = root / ".editor_snippets.json"
if snip_path.exists():
with open(snip_path, 'r') as f:
snippets = json.load(f)
for k, v in snippets.items():
self.save_snippet(k, v)
def load_settings_for_path(path): print(f"Migration complete. Imported {count} files.")
"""Returns a dict of settings for the specific path, or None."""
conn = get_db_connection() # --- PROJECT OPERATIONS ---
cursor = conn.cursor() def get_projects_in_dir(self, directory):
cursor.execute("SELECT params FROM settings WHERE path = ?", (path,)) """Returns list of filenames for a specific directory."""
cursor = self.conn.cursor()
# Ensure directory path format matches how we save it
dir_str = str(Path(directory).absolute())
cursor.execute("SELECT filename FROM projects WHERE parent_dir = ?", (dir_str,))
return [row['filename'] for row in cursor.fetchall()]
def load_project(self, full_path):
cursor = self.conn.cursor()
cursor.execute("SELECT data FROM projects WHERE path = ?", (str(full_path),))
row = cursor.fetchone() row = cursor.fetchone()
conn.close()
if row: if row:
return json.loads(row['params']) return json.loads(row['data'])
return None return None
def save_settings_for_path(path, settings_dict): def save_project(self, full_path, data, is_batch=False):
"""Saves the settings dict into the DB associated with the path.""" path_obj = Path(full_path)
conn = get_db_connection() path_str = str(path_obj.absolute())
cursor = conn.cursor() parent_str = str(path_obj.parent.absolute())
filename = path_obj.name
json_str = json.dumps(settings_dict)
timestamp = datetime.now()
cursor = self.conn.cursor()
cursor.execute(''' cursor.execute('''
INSERT INTO settings (path, params, updated_at) INSERT INTO projects (path, parent_dir, filename, data, is_batch, updated_at)
VALUES (?, ?, ?) VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(path) DO UPDATE SET ON CONFLICT(path) DO UPDATE SET
params=excluded.params, data=excluded.data,
is_batch=excluded.is_batch,
updated_at=excluded.updated_at updated_at=excluded.updated_at
''', (path, json_str, timestamp)) ''', (path_str, parent_str, filename, json.dumps(data), int(is_batch), datetime.now()))
self.conn.commit()
conn.commit() def delete_project(self, full_path):
conn.close() cursor = self.conn.cursor()
return f"Saved settings for: {path}" cursor.execute("SELECT count(*) FROM projects WHERE path = ?", (str(full_path),)) # Check existence
cursor.execute("DELETE FROM projects WHERE path = ?", (str(full_path),))
self.conn.commit()
# --- BATCH FUNCTIONS --- # --- CONFIG OPERATIONS ---
def load_app_config(self):
def log_batch_run(path, status, details_dict): cursor = self.conn.cursor()
conn = get_db_connection() cursor.execute("SELECT value FROM app_config WHERE key = 'main_config'")
cursor = conn.cursor() row = cursor.fetchone()
if row:
return json.loads(row['value'])
# Default Config
return {"last_dir": str(Path.cwd()), "favorites": []}
def save_app_config(self, config_dict):
cursor = self.conn.cursor()
cursor.execute(''' cursor.execute('''
INSERT INTO batch_log (timestamp, path, status, details) INSERT INTO app_config (key, value) VALUES ('main_config', ?)
VALUES (?, ?, ?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value
''', (datetime.now(), path, status, json.dumps(details_dict))) ''', (json.dumps(config_dict),))
self.conn.commit()
conn.commit() # --- SNIPPET OPERATIONS ---
conn.close() def load_snippets(self):
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM snippets")
return {row['name']: row['content'] for row in cursor.fetchall()}
# Initialize DB immediately when this module is imported def save_snippet(self, name, content):
init_db() cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO snippets (name, content) VALUES (?, ?)
ON CONFLICT(name) DO UPDATE SET content=excluded.content
''', (name, content))
self.conn.commit()
def delete_snippet(self, name):
cursor = self.conn.cursor()
cursor.execute("DELETE FROM snippets WHERE name = ?", (name,))
self.conn.commit()