diff --git a/pyproject.toml b/pyproject.toml index eb7ec6b..0a1b086 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,9 @@ dependencies = [ "sqlalchemy", "textual", + "tomli", + "tomli_w" + ] [template.plugins.default] diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index 380c4c2..1d2f11a 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -1,19 +1,21 @@ from pilgrim.database import Database from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.ui import UIApp -from pilgrim.utils import DirectoryManager +from pilgrim.utils import ConfigManager class Application: def __init__(self): - self.config_dir = DirectoryManager.get_config_directory() - self.database = Database() + self.config_manager = ConfigManager() + self.config_manager.read_config() # Chamar antes de criar o Database + self.database = Database(self.config_manager) session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) - self.ui = UIApp(session_manager) + self.ui = UIApp(session_manager, self.config_manager) def run(self): + print(f"URL do banco: {self.config_manager.database_url}") self.database.create() self.ui.run() diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index aba4219..8d472af 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -5,38 +5,24 @@ from pathlib import Path import os import shutil +from pilgrim.utils import ConfigManager + Base = declarative_base() -def get_database_path() -> Path: - """ - Get the database file path following XDG Base Directory specification. - Creates the directory if it doesn't exist. - """ - # Get home directory - home = Path.home() - - # Create .pilgrim directory if it doesn't exist - pilgrim_dir = home / ".pilgrim" - pilgrim_dir.mkdir(exist_ok=True) - - # Database file path - db_path = pilgrim_dir / "database.db" - - # If database doesn't exist in new location but exists in current directory, - # migrate it - if not db_path.exists(): - current_db = Path("database.db") - if current_db.exists(): - shutil.copy2(current_db, db_path) - print(f"Database migrated from {current_db} to {db_path}") - - return db_path + class Database: - def __init__(self): - db_path = get_database_path() + + def __init__(self, config_manager: ConfigManager): + self.db_path = config_manager.database_url + + # Garantir que o diretório existe + db_dir = os.path.dirname(self.db_path) + if not os.path.exists(db_dir): + os.makedirs(db_dir, exist_ok=True) + self.engine = create_engine( - f"sqlite:///{db_path}", + f"sqlite:///{self.db_path}", echo=False, connect_args={"check_same_thread": False}, ) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index e91f516..0e713a5 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -12,9 +12,9 @@ class NewDiaryModal(ModalScreen[str]): Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self,autoopen=True): + def __init__(self): super().__init__() - self.auto_open = autoopen + self.auto_open = self.app.config_manager.auto_open_new_diary self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input def compose(self) -> ComposeResult: diff --git a/src/pilgrim/ui/ui.py b/src/pilgrim/ui/ui.py index 2443f74..5557993 100644 --- a/src/pilgrim/ui/ui.py +++ b/src/pilgrim/ui/ui.py @@ -9,6 +9,7 @@ from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.screens.about_screen import AboutScreen from pilgrim.ui.screens.diary_list_screen import DiaryListScreen from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen +from pilgrim.utils import ConfigManager CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" @@ -16,9 +17,10 @@ CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" class UIApp(App): CSS_PATH = CSS_FILE_PATH - def __init__(self,service_manager: ServiceManager, **kwargs): + def __init__(self,service_manager: ServiceManager, config_manager: ConfigManager, **kwargs): super().__init__(**kwargs) self.service_manager = service_manager + self.config_manager = config_manager def on_mount(self) -> None: diff --git a/src/pilgrim/utils/__init__.py b/src/pilgrim/utils/__init__.py index f419fe1..b9fbd1b 100644 --- a/src/pilgrim/utils/__init__.py +++ b/src/pilgrim/utils/__init__.py @@ -1,3 +1,4 @@ from .directory_manager import DirectoryManager +from .config_manager import ConfigManager -__all__ = ['DirectoryManager'] +__all__ = ['DirectoryManager', 'ConfigManager'] diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py new file mode 100644 index 0000000..7a0f856 --- /dev/null +++ b/src/pilgrim/utils/config_manager.py @@ -0,0 +1,107 @@ +import os.path +from os import PathLike +from threading import Lock + +import tomli +import tomli_w + +from pilgrim.utils import DirectoryManager + + +class SingletonMeta(type): + _instances = {} + _lock: Lock = Lock() + + def __call__(cls, *args, **kwargs): + with cls._lock: + if cls not in cls._instances: + instance = super().__call__(*args, **kwargs) + cls._instances[cls] = instance + return cls._instances[cls] + + +class ConfigManager(metaclass=SingletonMeta): + def __init__(self): + self.database_url = None + self.database_type = None + self.auto_open_diary = None + self.auto_open_new_diary = None + self.config_dir = DirectoryManager.get_config_directory() + self.__data = None + + def read_config(self): + if os.path.exists(f"{DirectoryManager.get_config_directory()}/config.toml"): + try: + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: + data = tomli.load(f) + + except tomli.TOMLDecodeError as e: + raise ValueError(f"Invalid TOML configuration: {e}") + except Exception as e: + raise RuntimeError(f"Error reading configuration: {e}") + + self.__data = data + self.database_url = self.__data["database"]["url"] + self.database_type = self.__data["database"]["type"] + + if self.__data["settings"]["diary"]["auto_open_diary_on_startup"] == "": + self.auto_open_diary = None + self.auto_open_new_diary = self.__data["settings"]["diary"]["auto_open_on_creation"] + else: + print("Error: config.toml not found.") + self.create_config() + self.read_config() + + def create_config(self, config: dict = None): + # Garantir que o diretório de configuração existe + config_dir = DirectoryManager.get_config_directory() + if not os.path.exists(config_dir): + os.makedirs(config_dir, exist_ok=True) + + default = { + "database": { + "url": f"{config_dir}/database.db", + "type": "sqlite" + }, + "settings": { + "diary": { + "auto_open_diary_on_startup": "", + "auto_open_on_creation": False + } + } + } + if config is None: + config = default + + try: + with open(f"{config_dir}/config.toml", "wb") as f: + tomli_w.dump(config, f) + except Exception as e: + raise RuntimeError(f"Error creating configuration: {e}") + + def save_config(self): + if self.__data is None: + self.read_config() + if self.__data is None: + raise RuntimeError("Error reading configuration.") + + self.__data["database"]["url"] = self.database_url + self.__data["database"]["type"] = self.database_type + self.__data["settings"]["diary"]["auto_open_diary_on_startup"] = self.auto_open_diary or "" + self.__data["settings"]["diary"]["auto_open_on_creation"] = self.auto_open_new_diary + try: + self.create_config(self.__data) + except Exception as e: + raise RuntimeError(f"Error saving configuration: {e}") + + def set_config_dir(self, value): + self.config_dir = value + + def set_database_url(self, value: str): + self.database_url = value + + def set_auto_open_diary(self, value: str): + self.auto_open_diary = value + + def set_auto_open_new_diary(self, value: bool): + self.auto_open_new_diary = value diff --git a/src/pilgrim/utils/directory_manager.py b/src/pilgrim/utils/directory_manager.py index c6a0708..7a39670 100644 --- a/src/pilgrim/utils/directory_manager.py +++ b/src/pilgrim/utils/directory_manager.py @@ -1,4 +1,5 @@ import os +import shutil from pathlib import Path @@ -37,3 +38,26 @@ class DirectoryManager: def get_diary_images_directory(directory_name: str) -> Path: """Returns the images directory path for a specific diary.""" return DirectoryManager.get_diary_data_directory(directory_name) / "images" + + @staticmethod + def get_database_path() -> Path: + """ + Get the database file path following XDG Base Directory specification. + Creates the directory if it doesn't exist. + """ + pilgrim_dir = DirectoryManager.get_config_directory() + db_path = pilgrim_dir / "database.db" + + # If database doesn't exist in new location but exists in current directory, + # migrate it + if not db_path.exists(): + current_db = Path("database.db") + if current_db.exists(): + try: + shutil.copy2(current_db, db_path) + # Consider using logging instead of print + print(f"Database migrated from {current_db} to {db_path}") + except (OSError, shutil.Error) as e: + raise RuntimeError(f"Failed to migrate database: {e}") + + return db_path