feat: persistent DB host config, async DB ops, Exit button, test connection

- Save/load DB host from config.json (works both in dev and built .exe)
- All DB operations moved to background threads to prevent UI blocking
- Connection timeout set to 5s to avoid long hangs on unreachable host
- Added Test Connection button to Settings popup
- Added red Exit button fixed to bottom-right corner of main screen
- Updated DatabaseApp.spec with full Kivy deps (sdl2, glew, angle) and hidden imports
- PyInstaller-aware base path using sys.frozen for config.json persistence
This commit is contained in:
scheianu
2026-04-01 21:00:45 +03:00
parent 8ae60a77e4
commit c912bac2dc
4 changed files with 220 additions and 57 deletions

View File

@@ -1,6 +1,18 @@
import mysql.connector
from mysql.connector import Error
from typing import List, Tuple, Optional
import json
import os
import sys
# When frozen by PyInstaller, __file__ points to a temp folder that is deleted on exit.
# sys.executable points to the .exe location, which is persistent.
if getattr(sys, 'frozen', False):
_BASE_DIR = os.path.dirname(sys.executable)
else:
_BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILE = os.path.join(_BASE_DIR, 'config.json')
class DatabaseManager:
"""
@@ -9,12 +21,53 @@ class DatabaseManager:
"""
def __init__(self):
self.host = "localhost"
self.host = self._load_host()
self.database = "cantare_injectie"
self.user = "omron"
self.password = "Initial01!"
self.connection = None
self.init_database()
# init_database() is called asynchronously from the UI layer to avoid blocking
def _load_host(self) -> str:
"""Load the database host from the config file, falling back to localhost."""
try:
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, 'r') as f:
data = json.load(f)
return data.get('host', 'localhost')
except Exception as e:
print(f"Could not read config file: {e}")
return 'localhost'
def save_host(self, host: str):
"""Persist the database host to the config file."""
try:
data = {}
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, 'r') as f:
data = json.load(f)
data['host'] = host
with open(CONFIG_FILE, 'w') as f:
json.dump(data, f, indent=2)
except Exception as e:
print(f"Could not save config file: {e}")
def test_connection(self, host: str) -> tuple:
"""Test connectivity to the database using the given host. Returns (success: bool, message: str)."""
try:
test_conn = mysql.connector.connect(
host=host,
database=self.database,
user=self.user,
password=self.password,
connection_timeout=5
)
if test_conn.is_connected():
test_conn.close()
return True, f"Connected successfully to '{host}'"
except Error as e:
return False, str(e)
return False, "Connection failed"
def get_connection(self):
"""Get a database connection."""
@@ -24,7 +77,8 @@ class DatabaseManager:
host=self.host,
database=self.database,
user=self.user,
password=self.password
password=self.password,
connection_timeout=5
)
return self.connection
except Error as e: